jzoj 4243. 【五校联考6day1】c

Description

定义S 为十进制只由4 和7 组成的全体正整数的集合。
对于1 ≤ i ≤ N,给定ai。要求完成M 个操作:
add l r v 将i ∈ [l, r] 的所有ai 加上v
count l r 统计有多少i 满足i ∈ [l, r] 且 ai ∈ S

Input

第一行:两个正整数N、M。
第二行:N 个正整数代表ai。
之后M 行:每行代表一个操作。

Output

对于每个count 操作输出一行:一个整数代表答案。

Sample Input

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

Sample Output

1
0
1
1

Data Constraint

50% 的数据满足N,M ≤ 103
100% 的数据满足1 ≤ N,M ≤ 105; 1 ≤ ai ≤ 104; 1 ≤ v ≤ 104
数据保证所有操作结束后ai ≤ 104

这题就是分块做法。
我们可以暴力枚举一下S集合,算一算也就30个数。
然后我们分块然后对于每个块维护一个桶。
我们可以把问题转化成区间内有多少个数属于x(x属于S)
每次统计答案的时候分30种情况讨论即可。
上标:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 100010
using namespace std;
int n,m,a[N],bl[N],st,le[1010],ri[1010];
int sy[1010],t[321][10010],pl[1010];
bool bz[10010];
char ch;

inline int read()
{
	int x=0; char c=getchar();
	while (c<'0' || c>'9') c=getchar();
	while (c>='0' && c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
	return x;
}

void dfs(int x)
{
	if (x>10000) return;
	sy[++sy[0]]=x,bz[x]=1;
	dfs((x<<1)+(x<<3)+4);
	dfs((x<<1)+(x<<3)+7);
}

void update(int x)
{
	if (!pl[x]) return;
	memset(t[x],0,sizeof(t[x]));
	for (int i=le[x];i<=ri[x];i++)
		a[i]+=pl[x],t[x][a[i]]++;
	pl[x]=0;
}

void query(int l,int r)
{
	int s=0;
	if (bl[l]==bl[r])
	{
		update(bl[l]);
		for (int i=l;i<=r;i++)
			if (bz[a[i]]) s++;
		printf("%d
",s);
		return;
	}
	update(bl[l]);
	for (int i=l;i<=ri[bl[l]];i++)
		if (bz[a[i]]) s++;
	update(bl[r]);
	for (int i=le[bl[r]];i<=r;i++)
		if (bz[a[i]]) s++;
	for (int i=bl[l]+1;i<bl[r];i++)
		for (int j=1;j<=sy[0];j++)
			if (sy[j]>pl[i]) s+=t[i][sy[j]-pl[i]];
	printf("%d
",s);
	return;
}

void add(int l,int r,int v)
{
	if (bl[l]==bl[r])
	{
		for (int i=l;i<=r;i++)
		{
			t[bl[l]][a[i]]--;
			a[i]+=v;
			t[bl[l]][a[i]]++;
		}
		return;
	}
	for (int i=l;i<=ri[bl[l]];i++)
	{
		t[bl[l]][a[i]]--;
		a[i]+=v;
		t[bl[l]][a[i]]++;
	}
	for (int i=le[bl[r]];i<=r;i++)
	{
		t[bl[r]][a[i]]--;
		a[i]+=v;
		t[bl[r]][a[i]]++;
	}
	for (int i=bl[l]+1;i<bl[r];i++)
		pl[i]+=v;
}

int main()
{
	freopen("c.in","r",stdin);
	freopen("c.out","w",stdout); 
	n=read(),m=read(),st=sqrt(n);
	dfs(4),dfs(7);
	for (int i=1;i<=n;i++)
	{
		a[i]=read(),bl[i]=(i-1)/st+1;
		if (!le[bl[i]]) le[bl[i]]=i;
		ri[bl[i]]=i;
		t[bl[i]][a[i]]++;
	}
	for (int i=1,l,r,v;i<=m;i++)
	{
		scanf(" %c",&ch);
		if (ch=='a') l=read(),r=read(),v=read(),add(l,r,v);
		else l=read(),r=read(),query(l,r);
	}
	return 0;
}
转载需注明出处。
原文地址:https://www.cnblogs.com/jz929/p/11817568.html