我原来准备做方差的。。
结果发现不会维护两个标记。。
就是操作变成一个 a*x+b ,每次维护a , b 即可
加的时候a=1 ,b=v
乘的时候a=v ,b=0
1 #include <cstdio> 2 const long long Maxn=100010; 3 4 long long a[Maxn],n,P,l,r,c,m,type; 5 struct Node 6 { 7 long long mul,add,sum,len; 8 }tree[Maxn<<2]; 9 10 inline void Change(long long o,long long mul,long long add) 11 { 12 tree[o].mul=(tree[o].mul*mul)%P; 13 tree[o].add=(tree[o].add*mul+add)%P; 14 tree[o].sum=(tree[o].sum*mul+tree[o].len*add)%P; 15 } 16 inline void push_down(long long o) 17 { 18 Change(o<<1,tree[o].mul,tree[o].add); 19 Change(o<<1|1,tree[o].mul,tree[o].add); 20 tree[o].mul=1; tree[o].add=0; 21 } 22 inline void push_up(long long o) 23 { 24 tree[o].sum=(tree[o<<1].sum+tree[o<<1|1].sum)%P; 25 tree[o].len=tree[o<<1].len+tree[o<<1|1].len; 26 } 27 void Build(long long o,long long l,long long r) 28 { 29 tree[o].mul=1; tree[o].add=0; 30 if (l==r) {tree[o].sum=a[l]; tree[o].len=1; return;} 31 long long mid=(l+r)>>1; 32 Build(o<<1,l,mid),Build(o<<1|1,mid+1,r); 33 push_up(o); 34 } 35 void Mul(long long o,long long l,long long r,long long p,long long q,long long v) 36 { 37 if (l==p && r==q) 38 { 39 Change(o,v,0); 40 return; 41 } 42 push_down(o); 43 long long mid=(l+r)>>1; 44 if (q<=mid) Mul(o<<1,l,mid,p,q,v); 45 if (p>=mid+1) Mul(o<<1|1,mid+1,r,p,q,v); 46 if (p<=mid && q>=mid+1) 47 Mul(o<<1,l,mid,p,mid,v),Mul(o<<1|1,mid+1,r,mid+1,q,v); 48 push_up(o); 49 } 50 void Add(long long o,long long l,long long r,long long p,long long q,long long v) 51 { 52 if (l==p && r==q) 53 { 54 Change(o,1,v); 55 return; 56 } 57 push_down(o); 58 long long mid=(l+r)>>1; 59 if (q<=mid) Add(o<<1,l,mid,p,q,v); 60 if (p>=mid+1) Add(o<<1|1,mid+1,r,p,q,v); 61 if (p<=mid && q>=mid+1) 62 Add(o<<1,l,mid,p,mid,v),Add(o<<1|1,mid+1,r,mid+1,q,v); 63 push_up(o); 64 } 65 long long Sum(long long o,long long l,long long r,long long p,long long q) 66 { 67 if (l==p && r==q) return tree[o].sum; 68 long long mid=(l+r)>>1; 69 push_down(o); 70 if (q<=mid) return Sum(o<<1,l,mid,p,q); 71 if (p>=mid+1) return Sum(o<<1|1,mid+1,r,p,q); 72 if (p<=mid && q>=mid+1) 73 return (Sum(o<<1,l,mid,p,mid)+Sum(o<<1|1,mid+1,r,mid+1,q))%P; 74 } 75 int main() 76 { 77 // freopen("c.in","r",stdin); 78 scanf("%lld%lld",&n,&P); 79 for (long long i=1;i<=n;i++) scanf("%lld",&a[i]); 80 Build(1,1,n); 81 scanf("%lld",&m); 82 for (long long i=1;i<=m;i++) 83 { 84 scanf("%lld",&type); 85 if (type==1) 86 { 87 scanf("%lld%lld%lld",&l,&r,&c); 88 Mul(1,1,n,l,r,c); 89 } 90 if (type==2) 91 { 92 scanf("%lld%lld%lld",&l,&r,&c); 93 Add(1,1,n,l,r,c); 94 } 95 if (type==3) 96 { 97 scanf("%lld%lld",&l,&r); 98 printf("%lld ",Sum(1,1,n,l,r)); 99 } 100 } 101 return 0; 102 }
UPD:2016.6.14
突然发现好久没有写过分块了,想到这道可以分块,push_up写成push_down了..
1 #include <cstdio> 2 #include <cmath> 3 #include <cstring> 4 #include <iostream> 5 #define LL long long 6 using namespace std; 7 const LL Maxn=600010; 8 const LL Inf=0x3f3f3f3f; 9 LL a[Maxn],n,P,l,r,c,m,type,Block[Maxn]; 10 struct Node 11 { 12 LL mul,add,len,sum; 13 }tree[Maxn]; 14 15 inline void Change(LL o,LL mul,LL add) 16 { 17 tree[o].mul=(tree[o].mul*mul)%P; 18 tree[o].add=(tree[o].add*mul+add)%P; 19 tree[o].sum=(tree[o].sum*mul+tree[o].len*add)%P; 20 } 21 inline void push_down(LL o) 22 { 23 for (;Block[o]==Block[o-1];o--); 24 for (LL i=o;Block[o]==Block[i];i++) a[i]=(a[i]*tree[Block[i]].mul+tree[Block[i]].add)%P; 25 tree[Block[o]].mul=1,tree[Block[o]].add=0; 26 } 27 28 inline void push_up(LL o) 29 { 30 tree[Block[o]].sum=0; 31 for (;Block[o]==Block[o-1];o--); 32 for (LL i=o;Block[o]==Block[i];i++) tree[Block[o]].sum=(tree[Block[o]].sum+a[i])%P; 33 } 34 void Mul(LL p,LL q,LL v) 35 { 36 if (Block[p]==Block[q]) 37 { 38 push_down(p); 39 for (LL i=p;i<=q;i++) a[i]=(a[i]*v)%P; 40 push_up(p); 41 return; 42 } 43 for (LL i=Block[p]+1;i<Block[q];i++) Change(i,v,0); 44 push_down(p),push_down(q); 45 for (LL i=p;Block[i]==Block[p];i++) a[i]=(a[i]*v)%P; 46 for (LL i=q;Block[i]==Block[q];i--) a[i]=(a[i]*v)%P; 47 push_up(p),push_up(q); 48 } 49 50 void Add(LL p,LL q,LL v) 51 { 52 if (Block[p]==Block[q]) 53 { 54 push_down(p); 55 for (LL i=p;i<=q;i++) a[i]=(a[i]+v)%P; 56 push_up(p); 57 return; 58 } 59 for (LL i=Block[p]+1;i<Block[q];i++) Change(i,1,v); 60 push_down(p),push_down(q); 61 for (LL i=p;Block[i]==Block[p];i++) a[i]=(a[i]+v)%P; 62 for (LL i=q;Block[i]==Block[q];i--) a[i]=(a[i]+v)%P; 63 push_up(p),push_up(q); 64 } 65 LL Sum(LL p,LL q) 66 { 67 LL ret=0; 68 if (Block[p]==Block[q]) 69 { 70 push_down(p); 71 for (LL i=p;i<=q;i++) ret=(ret+a[i])%P; 72 return ret; 73 } 74 for (LL i=Block[p]+1;i<Block[q];i++) ret=(ret+tree[i].sum)%P; 75 push_down(p),push_down(q); 76 for (LL i=p;Block[i]==Block[p];i++) ret=(ret+a[i])%P; 77 for (LL i=q;Block[i]==Block[q];i--) ret=(ret+a[i])%P; 78 return ret; 79 } 80 int main() 81 { 82 scanf("%lld%lld",&n,&P); 83 for (LL i=1;i<=n;i++) scanf("%lld",&a[i]),a[i]%=P; 84 LL pos=(LL)sqrt(n); 85 for (LL i=1;i<=n;i++) Block[i]=(i-1)/pos+1; 86 memset(tree,0,sizeof(tree)); 87 for (LL i=1;i<=n;i++) tree[Block[i]].len++; 88 for (LL i=1;i<=n;i++) tree[Block[i]].mul=1; 89 for (LL i=1;i<=n;i++) tree[Block[i]].sum=(tree[Block[i]].sum+a[i])%P; 90 91 scanf("%lld",&m); 92 for (LL i=1;i<=m;i++) 93 { 94 scanf("%lld",&type); 95 if (type==1) 96 { 97 scanf("%lld%lld%lld",&l,&r,&c); 98 Mul(l,r,c); 99 } 100 if (type==2) 101 { 102 scanf("%lld%lld%lld",&l,&r,&c); 103 Add(l,r,c); 104 } 105 if (type==3) 106 { 107 scanf("%lld%lld",&l,&r); 108 printf("%lld ",Sum(l,r)); 109 } 110 } 111 return 0; 112 }