codves 4919 线段树练习4
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题目描述 Description
给你N个数,有两种操作
1:给区间[a,b]内的所有数都增加X
2:询问区间[a,b]能被7整除的个数输入描述 Input Description
第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数。如果第一个数是add,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是count,表示统计区间[a,b]能被7整除的个数
输出描述 Output Description
对于每个询问输出一行一个答案
样例输入 Sample Input
3
2 3 4
6
count 1 3
count 1 2
add 1 3 2
count 1 3
add 1 3 3
count 1 3
样例输出 Sample Output
0
0
0
1
数据范围及提示 Data Size & Hint
10%:1<N<=10,1<Q<=10
30%:1<N<=10000,1<Q<=10000
100%:1<N<=100000,1<Q<=100000
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100010;
struct node
{
int lazy,l,r;
int sum[8];
}tr[N<<2];
int arr[10];
inline void pushup(int ro)
{
for(int i=0;i<=6;i++) tr[ro].sum[i]=tr[ro<<1].sum[i]+tr[ro<<1|1].sum[i];
}
void build(int ro,int l,int r)
{
tr[ro].l=l,tr[ro].r=r;
if(l==r)
{
int a;
scanf("%d",&a);
tr[ro].sum[a%7]++;
}
else
{
int mid=(l+r)>>1;
build(ro<<1,l,mid);
build(ro<<1|1,mid+1,r);
pushup(ro);
}
return;
}
inline void down(int ro)
{
tr[ro<<1].lazy+=tr[ro].lazy;
tr[ro<<1|1].lazy+=tr[ro].lazy;
for(int i=0;i<=6;i++) arr[i]=0,arr[i]=tr[ro<<1].sum[i];
for(int i=0;i<=6;i++) tr[ro<<1].sum[(i+tr[ro].lazy)%7]=arr[i];
for(int i=0;i<=6;i++) arr[i]=0,arr[i]=tr[ro<<1|1].sum[i];
for(int i=0;i<=6;i++) tr[ro<<1|1].sum[(i+tr[ro].lazy)%7]=arr[i];
tr[ro].lazy=0;
}
void change(int ro,int l,int r,int add)
{
if(l<=tr[ro].l&&tr[ro].r<=r)
{
for(int i=0;i<=6;i++) arr[i]=0,arr[i]=tr[ro].sum[i];
for(int i=0;i<=6;i++) tr[ro].sum[(i+add)%7]=arr[i];
//printf("%d\n",add);
tr[ro].lazy+=add;
tr[ro].lazy%=7;
//for(int i=1;i<=20;i++) {for(int j=0;j<=6;j++) printf("%d ",tr[i].sum[j]);printf("%d %d\n",tr[i].l,tr[i].r);}
return;
}
if(tr[ro].lazy) down(ro);
int mid=(tr[ro].l+tr[ro].r)>>1;
if(l<=mid) change(ro<<1,l,r,add);
if(mid<r) change(ro<<1|1,l,r,add);
pushup(ro);
return;
}
long long int query(int ro,int l,int r)
{
if(l<=tr[ro].l&&tr[ro].r<=r) return tr[ro].sum[0];
if(tr[ro].lazy) down(ro);
long long int ans=0;
int mid=(tr[ro].l+tr[ro].r)>>1;
if(l<=mid) ans+=query(ro<<1,l,r);
if(r>mid) ans+=query(ro<<1|1,l,r);
return ans;
}
int main()
{
int n;
scanf("%d",&n);
build(1,1,n);
//for(int i=1;i<=20;i++) {for(int j=0;j<=6;j++) printf("%d ",tr[i].sum[j]);printf("%d %d\n",tr[i].l,tr[i].r);}
int m;
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
char pd[8];
scanf("%s",pd);
if(pd[0]=='a')
{
int a,b,x;
scanf("%d %d %d",&a,&b,&x);
change(1,a,b,x%7);
//for(int k=1;k<=20;k++) {for(int j=0;j<=6;j++) printf("%d ",tr[k].sum[j]);printf("%d %d\n",tr[k].l,tr[k].r);}
}
else
{
int l,r;
scanf("%d %d",&l,&r);
printf("%lld\n",query(1,l,r));
}
}
return 0;
}
关键是我们需要维护的东西是什么?
我们用一个数组存区间内%7后每个值的个数;
最后输出值为0的个数。