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(线段树多重标记下传)

BZOJ 1798 [Ahoi2009]Seq 维护序列seq

bzoj1798: [Ahoi2009]Seq 维护序列seq