Query
题目描述
万恶的大头又出现了!他正在玩一个智障游戏:打怪兽。
现在大头的屏幕上出现了一排怪兽,每只怪兽头上有一个血条,每次大头可以选择一个区间进行攻击,攻击值为 K ,这个区间中血量小于 K 的怪兽都会被大头无情地干掉,当然怪兽不会坐以待毙,对于一个区间的怪兽,他们会在某个时刻血量同时加 X 。
大头头虽然很大,但是 IQ 并不高,在座的各位选手都不知道比他高到哪里去了。这个时候大头使出了大招——作弊器,然而大头的作弊器并不高级只能将选择的区间内血量为 7 的倍数的怪兽干掉,问:他能干掉多少怪兽?
输入格式
第一行一个正整数 n ;
接下来 n 行 n 个整数;
再接下来一个正整数 Q ,表示操作的个数;
接下来 Q 行每行若干个整数。如果第一个数是 add ,后接 3 个正整数 a,b,X,表示在区间 [a,b] 内每个数增加 X,如果是 count,表示统计区间 [a,b] 能被 7 整除的个数。
输出格式
对于每个询问输出一行一个答案。
样例数据 1
输入
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
输出
0
0
0
1
解析:
线段树区间和,(区间取模? )。
在考场上打了半天最终在一个问题上卡住了,结果考完后5分钟分就调对了。。。
回到题目,很明显是一道线段树,我们令tree[ root ][ i ]表示区间 root 中模 7 余 i 的数字个数之和,于是就是模板了。。。
代码:
#include <bits/stdc++.h>
using namespace std;
const int Max=100010;
int n,m,ans,q;
int num[Max];
char ch[10];
int tree[Max<<2][10],add[Max<<2];
inline int get_int()
{
int x=0,f=1;
char c;
for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
if(c=='-') {f=-1;c=getchar();}
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
return x*f;
}
inline void update(int root){for(int i=0;i<=6;i++) tree[root][i] = tree[root<<1][i] + tree[root<<1|1][i];}
inline void calc(int root,int x)
{
int a[8];
for(int i=0;i<=6;i++) a[i] = tree[root][i];
for(int i=0;i<=6;i++) tree[root][(i + x) % 7] = a[i];
}
inline void pushdown(int root)
{
if(add[root])
{
add[root<<1] = (add[root<<1] + add[root]) % 7,calc(root<<1,add[root]);
add[root<<1|1] = (add[root<<1|1] + add[root]) % 7,calc(root<<1|1,add[root]);
add[root] = 0;
}
}
inline void build(int root,int l,int r)
{
if(l == r)
{
int x=num[l] % 7;
tree[root][x] = 1;
return;
}
int mid = l + r >> 1;
build(root<<1,l,mid),build(root<<1|1,mid+1,r);
update(root);
}
inline void Add(int root,int l,int r,int L,int R,int x)
{
if(L <= l && R >= r)
{
add[root] = (add[root] + x) % 7;
calc(root,x);
return;
}
int mid = l + r >> 1;
pushdown(root);
if(L <= mid) Add(root<<1,l,mid,L,R,x);
if(R > mid) Add(root<<1|1,mid+1,r,L,R,x);
update(root);
}
inline int Q(int root,int l,int r,int L,int R)
{
if(L <= l && R >= r) return tree[root][0];
int mid = l + r >> 1,ans=0;
pushdown(root);
if(L <= mid) ans += Q(root<<1,l,mid,L,R);
if(R > mid) ans += Q(root<<1|1,mid+1,r,L,R);
return ans;
}
inline void print(int x)
{
if(x > 9) print(x/10);
putchar('0' + x%10);
}
int main()
{
n=get_int();
for(int i=1;i<=n;i++) num[i]=get_int();
build(1,1,n);
q=get_int();
while(q--)
{
scanf("%s",ch+1);
if(ch[1] == 'a')
{
int l=get_int(),r=get_int(),x=get_int() % 7;
Add(1,1,n,l,r,x);
}
else
{
int l=get_int(),r=get_int();
ans = Q(1,1,n,l,r);
print(ans);
putchar('\n');
}
}
return 0;
}