BZOJ1798: [Ahoi2009]Seq 维护序列seq
【传送门:BZOJ1798】
简要题意:
给出一个长度为n个序列,有m个操作,共为三种操作:
1 x y c表示将x到y的值全部*c
2 x y c表示将x到y的值全部+c
3 x y求x到y的值的和
题解:
线段树嘛,区间修改加区间求值
但是关键是怎么处理乘和加的lazy标记的处理
首先肯定不能够像之前的题那样直接继承,因为有可能先乘后加再乘,这样子的话,直接继承会错误
所以我们设lazyc,lazyj表示当前继承时,值为x的数要变成lazyc*x+lazyj
如果要加c,就变成lazyc*x+lazyj+c
如果要乘c,就变成lazyc*x^c+lazyj*c就好了
参考代码:
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; struct node { int l,r,lc,rc; LL c,lazyc,lazyj; }tr[210000];int len; LL a[110000]; LL Mod; void update(int now) { int lc=tr[now].lc,rc=tr[now].rc; LL j=tr[now].lazyj,c=tr[now].lazyc; if(lc!=-1) { tr[lc].c=(LL(tr[lc].r-tr[lc].l+1)*j%Mod+(c*tr[lc].c)%Mod)%Mod; tr[lc].lazyc=(tr[lc].lazyc*c)%Mod; tr[lc].lazyj=((tr[lc].lazyj*c)%Mod+j)%Mod; } if(rc!=-1) { tr[rc].c=(LL(tr[rc].r-tr[rc].l+1)*j%Mod+(c*tr[rc].c)%Mod)%Mod; tr[rc].lazyc=(tr[rc].lazyc*c)%Mod; tr[rc].lazyj=((tr[rc].lazyj*c)%Mod+j)%Mod; } tr[now].lazyc=1;tr[now].lazyj=0; } void bt(int l,int r) { len++;int now=len; tr[now].l=l;tr[now].r=r;tr[now].c=0; tr[now].lc=tr[now].rc=-1; tr[now].lazyc=1;tr[now].lazyj=0; if(l<r) { int mid=(l+r)/2; tr[now].lc=len+1;bt(l,mid); tr[now].rc=len+1;bt(mid+1,r); } } void cheng(int now,int l,int r,LL c) { if(tr[now].l==l&&tr[now].r==r) { tr[now].c=(tr[now].c*c)%Mod; tr[now].lazyc=(tr[now].lazyc*c)%Mod; tr[now].lazyj=(tr[now].lazyj*c)%Mod; return ; } int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2; if(tr[now].lazyc!=1||tr[now].lazyj!=0) update(now); if(r<=mid) cheng(lc,l,r,c); else if(l>mid) cheng(rc,l,r,c); else cheng(lc,l,mid,c),cheng(rc,mid+1,r,c); tr[now].c=(tr[lc].c+tr[rc].c)%Mod; } void jia(int now,int l,int r,LL c) { if(tr[now].l==l&&tr[now].r==r) { tr[now].c=(tr[now].c+LL(r-l+1)%Mod*c)%Mod; tr[now].lazyj=(tr[now].lazyj+c)%Mod; return ; } int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2; if(tr[now].lazyc!=1||tr[now].lazyj!=0) update(now); if(r<=mid) jia(lc,l,r,c); else if(l>mid) jia(rc,l,r,c); else jia(lc,l,mid,c),jia(rc,mid+1,r,c); tr[now].c=(tr[lc].c+tr[rc].c)%Mod; } LL qiuhe(int now,int l,int r) { if(tr[now].l==l&&tr[now].r==r) return tr[now].c; int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2; if(tr[now].lazyc!=1||tr[now].lazyj!=0) update(now); if(r<=mid) return qiuhe(lc,l,r); else if(l>mid) return qiuhe(rc,l,r); else return (qiuhe(lc,l,mid)+qiuhe(rc,mid+1,r))%Mod; } int main() { int n; scanf("%d%lld",&n,&Mod); len=0;bt(1,n); for(int i=1;i<=n;i++) scanf("%lld",&a[i]),jia(1,i,i,a[i]); int m; scanf("%d",&m); for(int i=1;i<=m;i++) { int t; scanf("%d",&t); if(t==1) { int x,y;LL c; scanf("%d%d%lld",&x,&y,&c); cheng(1,x,y,c%Mod); } if(t==2) { int x,y;LL c; scanf("%d%d%lld",&x,&y,&c); jia(1,x,y,c%Mod); } if(t==3) { int x,y; scanf("%d%d",&x,&y); printf("%lld\n",qiuhe(1,x,y)); } } return 0; }
渺渺时空,茫茫人海,与君相遇,幸甚幸甚