洛谷3373 線段樹2(線段樹)
阿新 • • 發佈:2018-12-17
傳送門
【題目分析】
RT,就是線段樹的模板,支援區間乘、區間加、區間求和。
很有意思的一點是兩個標記的下傳,解決了就行了。
然後這道題,作為AHOI,竟然是個裸的模板!(可能年份久遠的原因吧。。。)兩個一毛一樣嘛!
【程式碼~】
#include<bits/stdc++.h> using namespace std; typedef long long LL; const LL MAXN=5e5+10; struct Tree{ LL l,r; LL sum,add,mul; }tr[MAXN<<2]; LL n,q,mod; LL a[MAXN]; LL Read() { LL i=0,f=1; char c; for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar()); if(c=='-') f=-1,c=getchar(); for(;c>='0'&&c<='9';c=getchar()) i=(i<<3)+(i<<1)+c-'0'; return i*f; } void sc(LL x) { if(x>=10) sc(x/10); putchar(x%10+48); } void push_up(LL root) { tr[root].sum=(tr[root<<1].sum+tr[root<<1|1].sum)%mod; } void push_down(LL root) { if(tr[root].mul!=1||tr[root].add) { LL mid=tr[root].l+tr[root].r>>1; tr[root<<1].sum=(tr[root<<1].sum*tr[root].mul+tr[root].add*(mid-tr[root].l+1))%mod; tr[root<<1|1].sum=(tr[root<<1|1].sum*tr[root].mul+tr[root].add*(tr[root].r-mid))%mod; tr[root<<1].add=(tr[root<<1].add*tr[root].mul+tr[root].add)%mod; tr[root<<1|1].add=(tr[root<<1|1].add*tr[root].mul+tr[root].add)%mod; tr[root<<1].mul=(tr[root<<1].mul*tr[root].mul)%mod; tr[root<<1|1].mul=(tr[root<<1|1].mul*tr[root].mul)%mod; tr[root].add=0; tr[root].mul=1; } } void build(LL root,LL l,LL r) { tr[root].mul=1; tr[root].l=l; tr[root].r=r; if(l==r) { tr[root].sum=a[l]; return ; } LL mid=l+r>>1; build(root<<1,l,mid); build(root<<1|1,mid+1,r); push_up(root); } void update1(LL root,LL l,LL r,LL L,LL R,LL key) { push_down(root); if(r<L||l>R) return ; if(L<=l&&r<=R) { tr[root].add=(tr[root].add+key)%mod; tr[root].sum=(tr[root].sum+key*(r-l+1))%mod; return ; } LL mid=l+r>>1; if(R<=mid) update1(root<<1,l,mid,L,R,key); else { if(L>mid) update1(root<<1|1,mid+1,r,L,R,key); else update1(root<<1,l,mid,L,mid,key),update1(root<<1|1,mid+1,r,mid+1,R,key); } push_up(root); } void update2(LL root,LL l,LL r,LL L,LL R,LL key) { push_down(root); if(r<L||l>R) return ; if(L<=l&&r<=R) { tr[root].mul=(tr[root].mul*key)%mod; tr[root].sum=(tr[root].sum*key)%mod; return ; } LL mid=l+r>>1; if(R<=mid) update2(root<<1,l,mid,L,R,key); else { if(L>mid) update2(root<<1|1,mid+1,r,L,R,key); else update2(root<<1,l,mid,L,mid,key),update2(root<<1|1,mid+1,r,mid+1,R,key); } push_up(root); } LL query(LL root,LL l,LL r,LL L,LL R) { push_down(root); if(l>R||r<L) return 0; if(L<=l&&r<=R) return tr[root].sum; LL mid=l+r>>1; if(R<=mid) return query(root<<1,l,mid,L,R); else { if(L>mid) return query(root<<1|1,mid+1,r,L,R); else return query(root<<1,l,mid,L,mid)+query(root<<1|1,mid+1,r,mid+1,R); } } int main() { n=Read(),mod=Read(); for(LL i=1;i<=n;++i) a[i]=Read(); build(1,1,n); q=Read(); while(q--) { LL cz=Read(),l=Read(),r=Read(); if(cz==1) { LL val=Read(); update2(1,1,n,l,r,val); } else { if(cz==2) { LL val=Read(); update1(1,1,n,l,r,val); } else sc(query(1,1,n,l,r)%mod),puts(""); } } return 0; }