codevs 4919
线段树:区间更新,区间查询(余数)
给你N个数,有两种操作
1:给区间[a,b]内的所有数都增加X
2:询问区间[a,b]能被7整除的个数
第一问直接上模板,第二问用一个数组x[]来记录除7余数的个数:如x[1]表示区间内除7余1 的数的个数,在进行区间更新如加5的时候将x的每一位向后移5 位
X[0] -> x[5]
X[1] -> x[6]
X[2] -> x[0]
X[3] -> x[1]
X[4] -> x[2]
X[5] -> x[3]
X[6] -> x[4]
Change 即为更改X[]的操作
#include <iostream>
#include <cstdio>
#include <cstring>
#define lson u << 1,l,mid
#define rson u << 1 | 1,mid + 1,r
#define p 7
using namespace std;
const int maxn = 100000 + 5;
int n,q,a,b,c,tt;
char s[100];
struct node
{
int sum,x[7],lazy;
}t[maxn << 2];
void pushup(int u)
{
t[u].sum = t[u << 1].sum + t[u << 1 | 1].sum;
for(int i = 0; i < p; ++i)
t[u].x[i] = t[u << 1].x[i] + t[u << 1 | 1].x[i];
}
void change(int u,int c)//为更改X[]的操作
{
int tx[10];
for(int i = 0; i < p; ++i) tx[i] = t[u].x[i];
for(int i = 0; i < p; ++i) t[u].x[i] = tx[(i - c + p) % p];
t[u].sum = t[u].x[0];
}
void pushdown(int u,int m)
{
if(t[u].lazy)
{
t[u << 1].lazy = (t[u << 1].lazy + t[u].lazy) % p;
t[u << 1 | 1].lazy = (t[u << 1 | 1].lazy + t[u].lazy) % p;
change(u << 1,t[u].lazy);
change(u << 1 | 1,t[u].lazy);
t[u].lazy = 0;
}
}
void build(int u,int l,int r)
{
if(l == r)
{
scanf("%d",&tt);
t[u].x[tt % p] = 1;
if(tt % p == 0) ++t[u].sum;
return;
}
int mid = (l + r) >> 1;
build(lson); build(rson);
pushup(u);
}
void update(int u,int l,int r,int a,int b,int c)
{
if(a <= l && r <= b)
{
t[u].lazy = (t[u].lazy + c) % p;
change(u,c);
return;
}
pushdown(u,r - l + 1);
int mid = (l + r) >> 1;
if(a <= mid) update(lson,a,b,c);
if(mid < b) update(rson,a,b,c);
pushup(u);
}
int query(int u,int l,int r,int a,int b)
{
if(a <= l && r <= b) return t[u].sum;
pushdown(u,r - l + 1);
int mid = (l + r) >> 1,ans = 0;
if(a <= mid) ans += query(lson,a,b);
if(mid < b) ans += query(rson,a,b);
return ans;
}
int main()
{
scanf("%d",&n);
build(1,1,n);
scanf("%d",&q);
for(int i = 1; i <= q; ++i)
{
scanf("\n%s",s);
if(s[0] == 'a')
{
scanf("%d%d%d",&a,&b,&c);
update(1,1,n,a,b,c % p);
}
else
{
scanf("%d%d",&a,&b);
printf("%d\n",query(1,1,n,a,b));
}
}
return 0;
}