【BZOJ】【1798】【AHOI2009】Seq维护序列

线段树

  属于线段树中级应用吧……

  要打两种标记:乘法和加法标记。一开始我想着可以像只有加法标记那样,永不下传,查询的时候依次累加就好了。后来发现不会写……只好每次update的时候……遇到标记!下传!query的时候遇到标记!下传!暴力地来搞……

  然后说下下传的细节:先传乘法,后传加法。因为传乘法标记的时候要连sum带add都要一起乘,如果先传add就会多乘……

  1 /**************************************************************
  2     Problem: 1798
  3     User: Tunix
  4     Language: C++
  5     Result: Accepted
  6     Time:3868 ms
  7     Memory:6748 kb
  8 ****************************************************************/
  9  
 10 //BZOJ 1798
 11 #include<cstdio>
 12 #include<cstring>
 13 #include<cstdlib>
 14 #include<iostream>
 15 #include<algorithm>
 16 #define rep(i,n) for(int i=0;i<n;++i)
 17 #define F(i,j,n) for(int i=j;i<=n;++i)
 18 #define D(i,j,n) for(int i=j;i>=n;--i)
 19 //using namespace std;
 20 const int N=100086;
 21 typedef long long LL;
 22 //#define debug
 23 int n,m,P,a[N];
 24 int mul[N<<2],add[N<<2],sum[N<<2];
 25  
 26 void read(int &v){
 27     v=0; int sign=1; char ch=getchar();
 28     while(ch<'0' || ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
 29     while(ch>='0' && ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
 30     v*=sign;
 31 }
 32 #define mid (l+r>>1)
 33 #define L (o<<1)
 34 #define R (o<<1|1)
 35  
 36 void Push_down(int o,int l,int r){
 37     if (mul[o]!=1){
 38         add[L]=((LL)add[L]*mul[o])%P; add[R]=((LL)add[R]*mul[o])%P;
 39         mul[L]=((LL)mul[L]*mul[o])%P; mul[R]=((LL)mul[R]*mul[o])%P;
 40         mul[o]=1;
 41     }
 42     if (add[o]!=0){
 43         add[L]=((LL)add[L]+add[o])%P; add[R]=((LL)add[R]+add[o])%P;
 44         add[o]=0;
 45     }  
 46 }
 47 void Push_up(int o,int l,int r){
 48     if (l<r) sum[o]=(sum[L]+sum[R])%P; else sum[o]=0;
 49     sum[o]=((LL)sum[o]*mul[o]+(LL)add[o]*(r-l+1))%P;
 50 }
 51 void build(int o,int l,int r){
 52     if (l==r) add[o]=sum[o]=a[l],mul[o]=1;
 53     else{
 54         build(L,l,mid);
 55         build(R,mid+1,r);
 56         add[o]=0; mul[o]=1;
 57         Push_up(o,l,r);
 58     }
 59 }
 60 int ql,qr;
 61 void update_add(int o,int l,int r,int v){
 62     if (ql<=l && qr>=r)
 63         add[o]=((LL)add[o]+v)%P;
 64     else{
 65         if (mul[o]!=1 || add[o]) Push_down(o,l,r);
 66         if (ql<=mid) update_add(L,l,mid,v); else Push_up(L,l,mid);
 67         if (qr>mid) update_add(R,mid+1,r,v); else Push_up(R,mid+1,r);
 68     }
 69     Push_up(o,l,r);
 70 }
 71 void update_mul(int o,int l,int r,int v){
 72     if (ql<=l && qr>=r)
 73         mul[o]=((LL)mul[o]*v)%P,add[o]=(LL)add[o]*v%P;
 74     else{
 75         if (mul[o]!=1 || add[o]) Push_down(o,l,r);
 76         if (ql<=mid) update_mul(L,l,mid,v); else Push_up(L,l,mid);
 77         if (qr>mid) update_mul(R,mid+1,r,v); else Push_up(R,mid+1,r);
 78     }
 79     Push_up(o,l,r);
 80 }
 81 int sumv;
 82 void query(int o,int l,int r){
 83     if (ql<=l && qr>=r)
 84         sumv=((LL)sumv+sum[o])%P;
 85     else{
 86         if (mul[o]!=1 || add[o]) {Push_down(o,l,r); Push_up(L,l,mid); Push_up(R,mid+1,r);}
 87         if (ql<=mid) query(L,l,mid);
 88         if (qr>mid) query(R,mid+1,r);
 89     }
 90 }
 91 int ans[N],cnt=0;
 92 int main(){
 93     #ifndef ONLINE_JUDGE
 94     freopen("input.txt","r",stdin);
 95 //  freopen("output.txt","w",stdout);
 96     #endif
 97     read(n); read(P);
 98     F(i,1,n) read(a[i]);
 99 //  F(i,1,n) printf("%d ",a[i]);
100 //  printf("\n");
101     build(1,1,n);
102      
103     read(m);
104 //  printf("m=%d\n",m);
105     int c,v;
106     F(i,1,m){
107         read(c); read(ql); read(qr);
108 //      printf("c=%d\n",c);
109         switch(c){
110             case 1: read(v); update_mul(1,1,n,v); break;
111             case 2: read(v); update_add(1,1,n,v); break;
112             case 3: sumv=0; query(1,1,n); ans[cnt++]=sumv;break;
113         }
114     }
115     rep(i,cnt-1) printf("%d\n",ans[i]);
116     printf("%d",ans[cnt-1]);
117     return 0;
118 }
View Code

 

posted @ 2015-01-16 23:23  Tunix  阅读(274)  评论(0编辑  收藏  举报