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