UESTC
来源:互联网 发布:淘宝网毛衣女装张大奕 编辑:程序博客网 时间:2024/06/07 06:55
/*思路:这个题目主要是用两个延迟标记的数组,一个加一个乘来处理。但是我们的问题是,当两个延迟标记到了 一个区间的时候我们是先加还是乘呢。如果弄清楚这个原理,这个题目,就出来了。大家看下这个啥 忘记叫啥了(sum[rt]+3)*2 ==sum*2+3*2,我们假设+3就是线段树加的延迟标记。乘2就是线段树的乘的延迟标记。我们遇到乘,就直接也同样的更新加的延迟标记,因为加如果没有的话,乘就是1,加就是0,当加来的时候我们每次都默认先乘,当有加的时候乘的就是1所以不变,当只有成的时候加的就是0, sum*a+3*b 当a等于1b等于0的时候,我们执行这个结果是不会改变的。当有乘延迟来的时候 就得将之前的 加的延迟标记 也得乘上这个数,就相当于哪里 +3 也得乘二,就是( sum[rt]+3)*2 ==sum*2+3*2 这样子 */ #include<stdio.h>#include<string.h>#include<stdlib.h> #define mem(a,b) memsesum(a,b,sizeof(a))using namespace std;#define N 100000*4+10typedef long long ll;ll ssss;ll n,p,m;ll sum[N];//求和数组 ll add[N];//延迟标记加 ll add1[N];//乘 void PushUp(int rt)//更新 { sum[rt]=(sum[rt*2]+sum[rt*2+1])%p;}void build(ll l,ll r,ll rsum)//建立线段树 { add1[rsum]=1,add[rsum]=0; if(l==r) { scanf("%lld",&sum[rsum]); return; } ll m=(l+r)>>1; build(l,m,rsum<<1); build(m+1,r,rsum<<1|1); PushUp(rsum);}void pushdown(ll rsum,ll num){ add[rsum<<1]=(add[rsum<<1]*add1[rsum]+add[rsum])%p; add[rsum<<1|1]=(add[rsum<<1|1]*add1[rsum]+add[rsum])%p; add1[rsum<<1]=(add1[rsum<<1]*add1[rsum])%p; add1[rsum<<1|1]=(add1[rsum<<1|1]*add1[rsum])%p; sum[rsum<<1]=(sum[rsum<<1]*add1[rsum]+(num-num/2)*add[rsum])%p; sum[rsum<<1|1]=(sum[rsum<<1|1]*add1[rsum]+(num/2)*add[rsum])%p; add[rsum]=0; add1[rsum]=1;}void updasuma(ll rsum,ll l,ll r,ll x,ll y,ll val,ll op){ if(x<=l&&r<=y) { if(op==1) { add[rsum]=(add[rsum]*val)%p; add1[rsum]=(add1[rsum]*val)%p; sum[rsum]=(sum[rsum]*val)%p; } else { add[rsum]=(add[rsum]+val); sum[rsum]=(sum[rsum]+(r-l+1)*val)%p; } return; } pushdown(rsum,r-l+1); ll m=(l+r)>>1; if(x<=m) updasuma(rsum<<1,l,m,x,y,val,op); if(y>m) updasuma(rsum<<1|1,m+1,r,x,y,val,op); PushUp(rsum);}void query(ll x,ll y,ll l,ll r,ll rsum){ if(x<=l&&y>=r) { ssss=(ssss%p+sum[rsum]%p)%p; return ; } pushdown(rsum,r-l+1); ll m=(l+r)>>1; if(x<=m) query(x,y,l,m,rsum<<1); if(y>m) query(x,y,m+1,r,rsum<<1|1);}int main(){ scanf("%lld%lld",&n,&p); build(1,n,1); scanf("%lld",&m); ll x,y,val,op; for(ll i=0;i<m;i++) { scanf("%lld",&op); if(op==1) { scanf("%lld%lld%lld",&x,&y,&val); updasuma(1,1,n,x,y,val,1); } else if(op==2) { scanf("%lld%lld%lld",&x,&y,&val); updasuma(1,1,n,x,y,val,2); } else { scanf("%lld%lld",&x,&y); ssss=0; query(x,y,1,n,1); printf("%lld\n",ssss); } }}
阅读全文
1 0
- UESTC
- UESTC
- UESTC
- UESTC
- UESTC
- UESTC
- UESTC
- UESTC
- UESTC
- UESTC
- UESTC
- UESTC
- UESTC
- UESTC
- UESTC
- UESTC
- UESTC
- UESTC
- BP神经网络代码示例
- SQL注入之堆叠注入
- swing初始化一个JFrame实现点击A界面的一个按钮,显示B界面,无论点击多少次,都只显示一个B界面
- 黑白棋子移动
- Docker教程3
- UESTC
- 常用ansible命令
- python:while循环的使用方法
- PCB 布线的直角走线、差分走线和蛇形线基础理论
- Oracle零基础入门.第一周课程总结
- 飞行员配对方案问题
- JAVA 表示时间:Date和SimpleDateFormat类表示时间
- 直接调用阿里云视频点播API实现视频播放
- 简单LinuxC程序关于加密(将任意长字符转换为定长整数)