【NOIP模拟】Query

                                                         Query

题目描述

万恶的大头又出现了!他正在玩一个智障游戏:打怪兽。

现在大头的屏幕上出现了一排怪兽,每只怪兽头上有一个血条,每次大头可以选择一个区间进行攻击,攻击值为 K ,这个区间中血量小于 K 的怪兽都会被大头无情地干掉,当然怪兽不会坐以待毙,对于一个区间的怪兽,他们会在某个时刻血量同时加 X 。

大头头虽然很大,但是 IQ 并不高,在座的各位选手都不知道比他高到哪里去了。这个时候大头使出了大招——作弊器,然而大头的作弊器并不高级只能将选择的区间内血量为 7 的倍数的怪兽干掉,问:他能干掉多少怪兽?

输入格式

第一行一个正整数 n ;
接下来 n 行 n 个整数;
再接下来一个正整数 Q ,表示操作的个数;
接下来 Q 行每行若干个整数。如果第一个数是 add ,后接 3 个正整数 a,b,X,表示在区间 [a,b] 内每个数增加 X,如果是 count,表示统计区间 [a,b] 能被 7 整除的个数。

输出格式

对于每个询问输出一行一个答案。

样例数据 1

输入


2 3 4
6
count 1 3 
count 1 2 
add 1 3 2 
count 1 3 
add 1 3 3 
count 1 3

输出




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;
}

猜你喜欢

转载自blog.csdn.net/m0_38083668/article/details/81369029
今日推荐