Multiples of 3Problem code: MULTQ3 |
There are N numbers a[0],a[1]..a[N - 1]. Initally all are 0. You have to perform two types of operations :
1) Increase the numbers between indices A and B (inclusive) by 1. This is represented by the command "0 A B"
2) Answer how many numbers between indices A and B (inclusive) are divisible by 3. This is represented by the command "1 A B".
Input :
The first line contains two integers, N and Q. Each of the next Q lines are either of the form "0 A B" or "1 A B" as mentioned above.
Output :
Output 1 line for each of the queries of the form "1 A B" containing the required answer for the corresponding query.
Sample Input :
4 7
1 0 3
0 1 2
0 1 3
1 0 0
0 0 3
1 3 3
1 0 3
Sample Output :
4
1
0
2
Constraints :
1 <= N <= 100000
1 <= Q <= 100000
0 <= A <= B <= N - 1
解决方案:这题要维护四个信息,1)除3余0的sum[0][rt],2)除3余1的sum[1][rt],3)除3余2的sum[2][rt],加上一个lazy标志add[rt],在加1的过程,即为三个状态:sum[0][rt]、sum[1][rt]、sum[2][rt]之间的转换,是加1转换还是加2转换由add[rt]来决定。
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#define MMAX 100003
using namespace std;
int sum[3][4*MMAX],add[4*MMAX];
int n,q;
int _sum;
void build(int rt,int L,int R)
{
if(L==R)
{
sum[0][rt]=1;
}
else
{
int l=rt*2,r=rt*2+1;
int M=(L+R)/2;
build(l,L,M);
build(r,M+1,R);
sum[0][rt]=sum[0][l]+sum[0][r];
}
}
void push_up(int rt)
{
int l=rt*2,r=rt*2+1;
sum[0][rt]=sum[0][l]+sum[0][r];
sum[1][rt]=sum[1][l]+sum[1][r];
sum[2][rt]=sum[2][l]+sum[2][r];
}
void push_down(int rt)
{
int l=rt*2,r=rt*2+1;
if(add[rt]!=0)
{
add[l]=(add[l]+add[rt])%3;
add[r]=(add[r]+add[rt])%3;
if(add[rt]==1)
{
int temp=sum[2][l];
sum[2][l]=sum[1][l];
sum[1][l]=sum[0][l];
sum[0][l]=temp;
}
else if(add[rt]==2)
{
int temp=sum[0][l];
sum[0][l]=sum[1][l];
sum[1][l]=sum[2][l];
sum[2][l]=temp;
}
if(add[rt]==1)
{
int temp=sum[2][r];
sum[2][r]=sum[1][r];
sum[1][r]=sum[0][r];
sum[0][r]=temp;
}
else if(add[rt]==2)
{
int temp=sum[0][r];
sum[0][r]=sum[1][r];
sum[1][r]=sum[2][r];
sum[2][r]=temp;
}
add[rt]=0;
}
}
void update(int rt,int L,int R,int sl,int sr)
{
if(sl<=L&&sr>=R)
{
int temp=sum[2][rt];
sum[2][rt]=sum[1][rt];
sum[1][rt]=sum[0][rt];
sum[0][rt]=temp;
add[rt]=(add[rt]+1)%3;
return ;
}
push_down(rt);
int m=(L+R)/2;
if(sl<=m) update(rt*2,L,m,sl,sr);
if(sr>m) update(rt*2+1,m+1,R,sl,sr);
push_up(rt);
}
void query(int rt,int L,int R,int ql,int qr){
if(ql<=L&&qr>=R){
_sum+=sum[0][rt];
}
else{
push_down(rt);
int m=(L+R)/2;
if(ql<=m)query(rt*2,L,m,ql,qr);
if(qr>m) query(rt*2+1,m+1,R,ql,qr);
}
}
int main()
{
while(~scanf("%d%d",&n,&q)){
build(1,1,n);
int a,b,c;
for(int i=1;i<=q;i++){
scanf("%d%d%d",&a,&b,&c);
if(a==1){
_sum=0;
query(1,1,n,b+1,c+1);
printf("%d\n",_sum);
}
else {
update(1,1,n,b+1,c+1);
}
}
}
return 0;
}