[bzoj5291]链上二次求和
Posted pywbktda
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[bzoj5291]链上二次求和相关的知识,希望对你有一定的参考价值。
记$bi=b_{i-1}+ai$,$ci=c_{i-1}+bi$,那么答案就是$sum_{i=l}^{r}sum_{j=0}^{n-i}b_{j+i}-bj=(r-l+1)cn-sum_{i=l-1}^{r-1}ci-sum_{i=n-r}^{n-l}ci$,用线段树维护ci数组
考虑对于[l,r,v]的修改操作(记$L=r-l+1$,注意不保证$lle r$),影响分为两部分:
1.$r<i$的部分,化简得到为$ci+=Lvcdot i-L(l+r-2)v/2$
2.$lle ile r$的部分,化简得到$ci+=v/2cdot i^{2}-v(2l-3)/2cdot i+(L+1)(L+2)v/2$
对于1,i和$i^{2}$分别建立一颗线段树即可维护,注意实现常数(比如懒标记为0就不用下传)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 200005 4 #define mod 1000000007 5 #define ny 500000004 6 #define L (k<<1) 7 #define R (L+1) 8 #define mid (l+r>>1) 9 int n,m,p,x,y,z,v[3][N<<2],laz[3][N<<2],f[3][N<<2]; 10 void build(int k,int l,int r){ 11 if (l==r){ 12 v[0][k]=1; 13 v[1][k]=l; 14 v[2][k]=1LL*l*l%mod; 15 return; 16 } 17 build(L,l,mid); 18 build(R,mid+1,r); 19 for(int i=0;i<3;i++)v[i][k]=(v[i][L]+v[i][R])%mod; 20 } 21 void upd(int p,int k,int x){ 22 laz[p][k]=(laz[p][k]+x)%mod; 23 f[p][k]=(f[p][k]+1LL*x*v[p][k])%mod; 24 } 25 void down(int k){ 26 for(int i=0;i<3;i++){ 27 if (!laz[i][k])continue; 28 upd(i,L,laz[i][k]); 29 upd(i,R,laz[i][k]); 30 laz[i][k]=0; 31 } 32 } 33 void update(int p,int k,int l,int r,int x,int y,int z){ 34 if ((l>y)||(x>r))return; 35 if ((x<=l)&&(r<=y)){ 36 upd(p,k,z); 37 return; 38 } 39 update(p,L,l,mid,x,y,z); 40 update(p,R,mid+1,r,x,y,z); 41 for(int i=0;i<3;i++)f[i][k]=(f[i][L]+f[i][R]+1LL*v[i][k]*laz[i][k])%mod; 42 } 43 void update(int x,int y,int z){ 44 int l=y-x+1,zz=1LL*z*ny%mod; 45 update(0,1,1,n,y+1,n,mod-1LL*l*(x+y-2)%mod*zz%mod); 46 update(1,1,1,n,y+1,n,1LL*l*z%mod); 47 update(0,1,1,n,x,y,(x-1LL)*(x-2)%mod*zz%mod); 48 update(1,1,1,n,x,y,(mod-2*x+3LL)*zz%mod); 49 update(2,1,1,n,x,y,zz); 50 } 51 int query(int k,int l,int r,int x,int y){ 52 if ((l>y)||(x>r))return 0; 53 if ((x<=l)&&(r<=y))return (0LL+f[0][k]+f[1][k]+f[2][k])%mod; 54 down(k); 55 return (query(L,l,mid,x,y)+query(R,mid+1,r,x,y))%mod; 56 } 57 int main(){ 58 scanf("%d%d",&n,&m); 59 build(1,1,n); 60 for(int i=1;i<=n;i++){ 61 scanf("%d",&x); 62 update(i,i,x); 63 } 64 for(int i=1;i<=m;i++){ 65 scanf("%d%d%d",&p,&x,&y); 66 if (x>y)swap(x,y); 67 if (p==1){ 68 scanf("%d",&z); 69 update(x,y,z); 70 } 71 if (p==2){ 72 x=max(x,1); 73 int s1=query(1,1,n,n,n)*(y-x+1LL)%mod; 74 int s2=(query(1,1,n,max(x-1,1),y-1)+query(1,1,n,max(n-y,1),n-x))%mod; 75 printf("%d ",(s1-s2+mod)%mod); 76 } 77 } 78 }
以上是关于[bzoj5291]链上二次求和的主要内容,如果未能解决你的问题,请参考以下文章