这道题主要要注意在成段更新这种类型的题目中,询问也要更新叶子结点的信息。
#include<stdio.h>
#include<string.h>
int n,m,setv[4000000][4],ans;
void pushup(int rt)
{
int lt=rt<<1;
int t=(rt<<1)|1;
setv[rt][1]=setv[lt][1]+setv[t][1];
setv[rt][2]=setv[lt][2]+setv[t][2];
setv[rt][0]=setv[lt][0]+setv[t][0];
}
void build(int rt,int l,int r)
{
if(l==r)
{
setv[rt][0]=1;
}
else
{
int mid=(l+r)>>1;
build(rt*2,l,mid);
build(rt*2+1,mid+1,r);
pushup(rt);
}
}
void pushdown(int rt,int l,int r)
{
int x=rt<<1,y=x|1;
if(setv[rt][3]==1)
{
setv[x][3]=(setv[x][3]+setv[rt][3])%3;
setv[y][3]=(setv[y][3]+setv[rt][3])%3;
int temp=setv[x][1];
setv[x][1]=setv[x][0];
setv[x][0]=setv[x][2];
setv[x][2]=temp;
temp=setv[y][1];
setv[y][1]=setv[y][0];
setv[y][0]=setv[y][2];
setv[y][2]=temp;
setv[rt][3]=0;
}
else if(setv[rt][3]==2)
{
setv[x][3]=(setv[x][3]+setv[rt][3])%3;
setv[y][3]=(setv[y][3]+setv[rt][3])%3;
int temp=setv[x][2];
setv[x][2]=setv[x][0];
setv[x][0]=setv[x][1];
setv[x][1]=temp;
temp=setv[y][2];
setv[y][2]=setv[y][0];
setv[y][0]=setv[y][1];
setv[y][1]=temp;
setv[rt][3]=0;
}
}
void update(int rt,int l,int r,int a,int b)
{
if(a<=l&&b>=r)
{
setv[rt][3]=(setv[rt][3]+1)%3;
int temp=setv[rt][1];
setv[rt][1]=setv[rt][0];
setv[rt][0]=setv[rt][2];
setv[rt][2]=temp;
return;
}
int mid=(l+r)>>1;
pushdown(rt,l,r);
if(a<=mid)
update(rt*2,l,mid,a,b);
if(b>mid)
update(rt*2+1,mid+1,r,a,b);
pushup(rt);
}
int query(int rt,int l,int r,int a,int b)
{
if(a<=l&&r<=b)
{
return setv[rt][0];
}
pushdown(rt,l,r);//记得要更新叶子结点。
int mid=(l+r)/2;
if(b<=mid)
return query(rt*2,l,mid,a,b);
else if(a>mid)
return query(rt*2+1,mid+1,r,a,b);
else return query(rt*2,l,mid,a,b)+query(rt*2+1,mid+1,r,a,b);
}
int main()
{
freopen("t.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
build(1,1,n);
int i,q,a,b;
for(i=0;i<m;i++)
{
scanf("%d%d%d",&q,&a,&b);
a++;b++;
if(q==0)
update(1,1,n,a,b);
else
{
ans=query(1,1,n,a,b);
printf("%d\n",ans);
}
}
}
return 0;
}