正题
第三题:[AHOI2009]维护序列
这道题是线段树的模板,只要用lazy记录一下即可,注意处理两个lazy(加和乘)的时候,注意运用乘法分配律。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define LL long long
int n,m;
LL mod;
struct tree{
int x,y,ls,rs;
LL c,lzm,lza;
}s[200010];
int len=0;
void pushdown(int p){
int ls=s[p].ls,rs=s[p].rs;
s[ls].lzm=s[ls].lzm*s[p].lzm%mod;
s[rs].lzm=s[rs].lzm*s[p].lzm%mod;
s[ls].lza=(s[ls].lza*s[p].lzm%mod+s[p].lza)%mod;
s[rs].lza=(s[rs].lza*s[p].lzm%mod+s[p].lza)%mod;
s[ls].c=(s[ls].c*s[p].lzm%mod+(s[ls].y-s[ls].x+1)*s[p].lza%mod)%mod;
s[rs].c=(s[rs].c*s[p].lzm%mod+(s[rs].y-s[rs].x+1)*s[p].lza%mod)%mod;
s[p].lzm=1;s[p].lza=0;
s[p].c=s[s[p].ls].c+s[s[p].rs].c;
}
void bt(int x,int y){
len++;
s[len].x=x;s[len].y=y;
s[len].ls=s[len].rs=-1;
s[len].c=0;
s[len].lzm=1;s[len].lza=0;
if(x==y) return ;
int i=len,mid=(x+y)/2;
s[i].ls=len+1;bt(x,mid);
s[i].rs=len+1;bt(mid+1,y);
}
void mult(int p,int x,int y,LL op){
if(s[p].x==x && s[p].y==y){
s[p].lzm=s[p].lzm*op%mod;
s[p].lza=s[p].lza*op%mod;
s[p].c=s[p].c*op%mod;
return ;
}
pushdown(p);
int mid=s[s[p].ls].y;
if(y<=mid) mult(s[p].ls,x,y,op);
else if(x>mid) mult(s[p].rs,x,y,op);
else mult(s[p].ls,x,mid,op),mult(s[p].rs,mid+1,y,op);
s[p].c=(s[s[p].ls].c+s[s[p].rs].c)%mod;
}
void add(int p,int x,int y,LL op){
if(s[p].x==x && s[p].y==y){
s[p].lza=(s[p].lza+op)%mod;
s[p].c=(s[p].c+op*(s[p].y-s[p].x+1)%mod)%mod;
return ;
}
pushdown(p);
int mid=s[s[p].ls].y;
if(y<=mid) add(s[p].ls,x,y,op);
else if(x>mid) add(s[p].rs,x,y,op);
else add(s[p].ls,x,mid,op),add(s[p].rs,mid+1,y,op);
s[p].c=(s[s[p].ls].c+s[s[p].rs].c)%mod;
}
LL get_tot(int p,int x,int y){
if(s[p].x==x && s[p].y==y)
return s[p].c;
pushdown(p);
int mid=s[s[p].ls].y;
if(y<=mid) return get_tot(s[p].ls,x,y);
else if(x>mid) return get_tot(s[p].rs,x,y);
else return (get_tot(s[p].ls,x,mid)+get_tot(s[p].rs,mid+1,y))%mod;
}
int main(){
scanf("%d %lld",&n,&mod);
bt(1,n);
for(int i=1;i<=n;i++) {
int x;
scanf("%d",&x);
add(1,i,i,x);
}
scanf("%d",&m);
int k,x,y;
LL op;
for(int i=1;i<=m;i++){
scanf("%d %d %d",&k,&x,&y);
if(k==1 || k==2) scanf("%lld",&op);
if(k==1) mult(1,x,y,op);
else if(k==2) add(1,x,y,op);
else printf("%lld\n",get_tot(1,x,y));
}
}