![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstring> #include<cstdio> #include<ctime> #include<algorithm> #define L(x) (x<<1) #define R(x) (x<<1|1) #define INF 2100000000 #define maxn 100100 #define intt long long #define mo 5201314 using namespace std; intt ax,ay,x,y,q,c; intt n,m; struct qaq{ intt maxx,deladd; intt delx; }tree[maxn*4]; intt read(){ intt f=1; intt k=0; char c=getchar(); while(c>'9'||c<'0'){ if(c=='-') f=-1; c=getchar(); } while(c>='0'&&c<='9'){ k=(k<<3)+(k<<1)+c-'0'; c=getchar(); } return f*k; } void push_down(intt id,intt l,intt r){ if(tree[id].delx==1&&tree[id].deladd==0) return; intt tad=tree[id].deladd; intt txx=tree[id].delx; intt mid=(l+r)>>1; tree[L(id)].deladd=(tree[L(id)].deladd*txx+tad)%mo; tree[R(id)].deladd=(tree[R(id)].deladd*txx+tad)%mo; tree[L(id)].delx=(tree[L(id)].delx*txx)%mo; tree[R(id)].delx=(tree[R(id)].delx*txx)%mo; tree[L(id)].maxx=(tree[L(id)].maxx*txx+(mid-l+1)*tad)%mo; tree[R(id)].maxx=(tree[R(id)].maxx*txx+(r-(mid+1)+1)*tad)%mo; tree[id].deladd=0; tree[id].delx=1; return; } void build(intt l,intt r,intt id,intt v){ if(l>y||r<x) return; tree[id].delx=1; tree[id].deladd=0; if(x<=l&&r<=y){ tree[id].maxx=v; //cout<<v<<endl; return; } intt mid=(l+r)>>1; build(l,mid,L(id),v); build(mid+1,r,R(id),v); tree[id].maxx=(tree[L(id)].maxx+tree[R(id)].maxx)%mo; //cout<<tree[id].maxx<<endl; return; } void updatax(intt l,intt r,intt id,intt v){ if(l>y||r<x) return; if(x<=l&&r<=y){ tree[id].deladd=(tree[id].deladd*v)%mo; tree[id].delx=(tree[id].delx*v)%mo; tree[id].maxx=(tree[id].maxx*v)%mo; return; } push_down(id,l,r); intt mid=(l+r)>>1; updatax(l,mid,L(id),v); updatax(mid+1,r,R(id),v); tree[id].maxx=(tree[L(id)].maxx+tree[R(id)].maxx)%mo; return; } void updataadd(intt l,intt r,intt id,intt v){ if(l>y||r<x) return; if(x<=l&&r<=y){ tree[id].deladd=(tree[id].deladd+v)%mo; tree[id].maxx=(tree[id].maxx+(r-l+1)*v)%mo; return; } push_down(id,l,r); intt mid=(l+r)>>1; updataadd(l,mid,L(id),v); updataadd(mid+1,r,R(id),v); tree[id].maxx=(tree[L(id)].maxx+tree[R(id)].maxx)%mo; return; } intt findit(int l,int r,int id){ if(l>y||r<x) return 0; if(x<=l&&r<=y){ //cout<<tree[id]. return tree[id].maxx%mo; } push_down(id,l,r); intt mid=(l+r)>>1; intt t1=findit(l,mid,L(id)); intt t2=findit(mid+1,r,R(id)); return (t1+t2)%mo; } int main(){ //freopen("a.txt","r",stdin); //freopen("b.txt","w",stdout); memset(tree,0,sizeof(tree)); n=read(); m=read(); //cout<<n<<' '<<m<<endl; for(int i=1;i<=n;++i){ c=read(); x=y=i; build(1,n,1,c); } for(int i=1;i<=m;++i){ q=read(); ax=read(); ay=read(); if(q==1){ x=ax; y=ay; c=read(); updatax(1,n,1,c); } else if(q==2){ x=ax; y=ay; c=read(); updataadd(1,n,1,c); } else{ x=ax; y=ay; cout<<findit(1,n,1)%mo<<endl; } } //cout<<"Runtime:"<<double(1.0*clock()/1000.0)<<"S!"<<endl; return 0; }
先放代码.....
这道题的难点在于1号操作,也就是乘法。裸的线段树,但是是双偏移量,还要控制好次序,代码慢慢看就行了。。