【AHOI2009】【BZOJ1798】Seq 维护序列seq(线段树模板,易错提醒)
problem
- 给定一个长为n的序列,m次询问
- 每次询问有3种操作
1、一段区间全部乘一个值
2、一段区间全部加一个值
3、询问一段区间和%P
solution
不就一颗线段树么,看朕10分钟A掉。。。
30分钟过后:md我脑残了吧,连线段树都写不来了?还爆栈???
1小时过后:我靠,WA什么鬼,样例是水做的么?
2小时过后:什么垃圾题,还不让下数据。我用线段树模板题调。
3小时过后:朕今天就不信邪了!!!
线段树智障错法整理:
1、add,mul,query都要加pushdown。
2、和值有关的都开long long , query千万记得mod
3、递归的地方if是L不是l。
4、4倍空间、
5、调试:C++重载函数(参数不同可以同名),直接找个不同参数的复制过去调。
6、不行就重写!!!重写比调试快!!!!!10mins重写,1000mins调试?
codes
#include<iostream>
using namespace std;
struct SegmentTree{
typedef long long LL;
#define maxn 500010
#define lch p<<1
#define rch p<<1|1
struct node{
LL val, addmark, mulmark;
}sgt[maxn<<2];
int mod;
void build(int p, int l, int r){
sgt[p].addmark = 0, sgt[p].mulmark = 1;
if(l == r){
cin>>sgt[p].val;
return ;
}
int mid = l+r>>1;
build(lch,l,mid);
build(rch,mid+1,r);
sgt[p].val = (sgt[lch].val+sgt[rch].val)%mod;
return ;
}
void pushdown(int p, int l, int r){
if(sgt[p].addmark==0&&sgt[p].mulmark==1)return ;
//父节点标记
LL t1 = sgt[p].addmark, t2 = sgt[p].mulmark;
sgt[p].addmark = 0, sgt[p].mulmark = 1;
//维护标记
int mid = l+r>>1;
sgt[lch].mulmark *= t2, sgt[lch].mulmark %= mod;
sgt[rch].mulmark *= t2, sgt[rch].mulmark %= mod;
sgt[lch].addmark = (sgt[lch].addmark*t2+t1)%mod;
sgt[rch].addmark = (sgt[rch].addmark*t2+t1)%mod;
//更新值
sgt[lch].val = (sgt[lch].val*t2+t1*(mid-l+1))%mod;
sgt[rch].val = (sgt[rch].val*t2+t1*(r-mid))%mod;
return ;
}
void add(int p, int l, int r, int L, int R, LL v){
if(L<=l && r<=R){
sgt[p].val += (r-l+1)*v;
sgt[p].val %= mod;
sgt[p].addmark += v;
sgt[p].addmark %= mod;
return ;
}
pushdown(p,l,r);
int mid = l+r>>1;
if(L<=mid)add(lch,l,mid,L,R,v);//是L不是l
if(R>mid)add(rch, mid+1, r,L,R,v);
sgt[p].val = (sgt[lch].val+sgt[rch].val)%mod;
}
void times(int p, int l, int r, int L, int R, LL v){
if(L<=l && r<=R){
sgt[p].val *= v;
sgt[p].val %= mod;
sgt[p].mulmark *= v;
sgt[p].mulmark %= mod;
sgt[p].addmark *= v;
sgt[p].addmark %= mod;
return ;
}
pushdown(p,l,r);
int mid = (l+r)/2;
if(L<=mid)times(lch,l,mid,L,R,v);
if(R>mid)times(rch,mid+1,r,L,R,v);
sgt[p].val = (sgt[lch].val+sgt[rch].val)%mod;
}
LL query(int p, int l, int r, int L, int R){
if(L<=l && r<=R)return sgt[p].val;
pushdown(p,l,r);
LL mid = l+r>>1, ans = 0;
if(L<=mid)ans += query(lch,l,mid,L,R);
if(R>mid)ans += query(rch,mid+1,r,L,R);
return ans%mod;
}
}sgt;
int main(){
int n, m, q;
cin>>n>>q;
sgt.mod = q;
sgt.build(1,1,n);
cin>>m;
for(int i = 1; i <= m; i++){
int op, l, r, v;
cin>>op;
if(op==1){
cin>>l>>r>>v;
sgt.times(1,1,n,l,r,v);
}else if(op==2){
cin>>l>>r>>v;
sgt.add(1,1,n,l,r,v);
}else{
cin>>l>>r;
cout<<(sgt.query(1,1,n,l,r))<<'\n';
}
}
return 0;
}