线段树
属于线段树中级应用吧……
要打两种标记:乘法和加法标记。一开始我想着可以像只有加法标记那样,永不下传,查询的时候依次累加就好了。后来发现不会写……只好每次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 }
时间: 2024-10-25 01:06:36