bzoj 1798 [Ahoi2009]Seq 维护序列seq(线段树+传标)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1798 [Ahoi2009]Seq 维护序列seq(线段树+传标)相关的知识,希望对你有一定的参考价值。
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=1798
【题意】
给定一个序列,要求提供区间乘/加,以及区间求和的操作
【思路】
线段树+传标。
下传标记的方式可以类比这里 click here
【代码】
1 #include<set> 2 #include<cmath> 3 #include<queue> 4 #include<vector> 5 #include<cstdio> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt) 10 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 11 using namespace std; 12 13 typedef long long ll; 14 const int N = 2e5+10; 15 16 ll read() { 17 char c=getchar(); 18 ll f=1,x=0; 19 while(!isdigit(c)) { 20 if(c==\'-\') f=-1; c=getchar(); 21 } 22 while(isdigit(c)) 23 x=x*10+c-\'0\',c=getchar(); 24 return x*f; 25 } 26 27 int MOD ; 28 29 struct Tnode { 30 int u,l,r; 31 ll sum,add,mul; 32 void mulv(ll x) ; 33 void addv(ll x) ; 34 void pushdown() ; 35 void maintain() ; 36 } T[N<<2] ; 37 void Tnode::mulv(ll x) { 38 mul=(mul*x)%MOD; 39 sum=(sum*x)%MOD; 40 add=(add*x)%MOD; 41 } 42 void Tnode::addv(ll x) { 43 sum=(sum+(r-l+1)*x)%MOD; 44 add=(add+x)%MOD; 45 } 46 void Tnode::pushdown() { 47 if(mul!=1) { 48 T[u<<1].mulv(mul); 49 T[u<<1|1].mulv(mul); 50 mul=1; 51 } 52 if(add) { 53 T[u<<1].addv(add); 54 T[u<<1|1].addv(add); 55 add=0; 56 } 57 } 58 void Tnode::maintain() { 59 sum=(T[u<<1].sum+T[u<<1|1].sum)%MOD; 60 } 61 void update(int u,int L,int R,int x,int flag) { 62 T[u].pushdown(); 63 if(L<=T[u].l&&T[u].r<=R) { 64 if(flag==0) T[u].addv(x); 65 else T[u].mulv(x); 66 } else { 67 int mid=T[u].l+T[u].r>>1; 68 if(L<=mid) update(u<<1,L,R,x,flag); 69 if(mid<R) update(u<<1|1,L,R,x,flag); 70 T[u].maintain(); 71 } 72 } 73 ll query(int u,int L,int R) { 74 T[u].pushdown(); 75 if(L<=T[u].l&&T[u].r<=R) 76 return T[u].sum; 77 else { 78 int mid=T[u].l+T[u].r>>1; 79 ll ans=0; 80 if(L<=mid) ans=(ans+query(u<<1,L,R))%MOD; 81 if(mid<R) ans=(ans+query(u<<1|1,L,R))%MOD; 82 return ans; 83 } 84 } 85 86 int n,m; ll a[N]; 87 88 void build(int u,int l,int r) { 89 T[u]=(Tnode){u,l,r,0,0,1}; 90 if(l==r) { 91 T[u].sum=a[l]%MOD; 92 return ; 93 } else { 94 int mid=l+r>>1; 95 build(u<<1,l,mid); 96 build(u<<1|1,mid+1,r); 97 T[u].maintain(); 98 } 99 } 100 /* Debug 101 int print(int u) { 102 T[u].pushdown(); 103 if(T[u].l==T[u].r) printf("%d,%d\\n",T[u].l,T[u].v); 104 else { 105 print(u<<1),print(u<<1|1); 106 } 107 } 108 */ 109 int main() 110 { 111 // freopen("in.in","r",stdin); 112 // freopen("out.out","w",stdout); 113 n=read(),MOD=read(); 114 FOR(i,1,n) a[i]=read(); 115 build(1,1,n); 116 m=read(); 117 int op,l,r,x; 118 FOR(i,1,m) { 119 op=read(),l=read(),r=read(); 120 if(op==1) { 121 x=read(); 122 update(1,l,r,x,1); 123 } else 124 if(op==2) { 125 x=read(); 126 update(1,l,r,x,0); 127 } else { 128 printf("%lld\\n",query(1,l,r)); 129 } 130 } 131 return 0; 132 }
P.S.我竟然蛋疼的存了一个v,还一本正经地累计到sum里 <_<
以上是关于bzoj 1798 [Ahoi2009]Seq 维护序列seq(线段树+传标)的主要内容,如果未能解决你的问题,请参考以下文章
bzoj1798: [Ahoi2009]Seq 维护序列seq(线段树)
BZOJ1798 [Ahoi2009]Seq 维护序列seq
bzoj 1798 [Ahoi2009]Seq 维护序列seq(线段树+传标)
bzoj1798: [Ahoi2009]Seq 维护序列seq(线段树多重标记下传)