题目链接:http://codeforces.com/problemset/problem/121/E
题意:幸运数是指只由4,7组成的数,例如4,7,47,74,447……,这道题先给你n个数的数组,再给你m个操作,操作有两种:1、count l r(计算[l,r]区间内幸运数的总数,并输出结果);2、add l r d(区间内的每个数都加d)
思路:由于数组中每个数都小于104,所以只要现对于小于104的数判断是否是幸运数,再将是幸运数的数的每个子节点值赋值为1在求出区间和,区间和就是幸运数的总数
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
#define N 10005
using namespace std;
queue<int>q;
int vis[N],in[N<<5],num[N<<5],n;
void init()
{
memset(vis,0,sizeof(vis));
while(!q.empty())
q.pop();
q.push(0);
while(q.front()<N)
{
vis[q.front()]=1;
q.push(q.front()*10+4);
q.push(q.front()*10+7);
q.pop();
}
}
int low_bit(int t)
{
return t&(-t);
}
int getSum(int end)
{
int sum=0;
while(end>0)
{
sum+=in[end];
end-=low_bit(end);
}
return sum;
}
void Add(int pos,int num)
{
while(pos<=n)
{
in[pos]+=num;
pos+=low_bit(pos);
}
}
int main()
{
init();
int m,a,b,c,ans;
char s[10];
scanf("%d%d",&n,&m);
memset(in,0,sizeof(in));
for(int i=1;i<=n;i++)
{
scanf("%d",&num[i]);
if(vis[num[i]])
Add(i,1);
}
while(m--)
{
scanf("%s",s);
if(s[0]=='a')
{
scanf("%d%d%d",&a,&b,&c);
if(!c)
continue;
for(int i=a;i<=b;i++)
{
if(vis[num[i]])
Add(i,-1);
num[i]+=c;
if(vis[num[i]])
Add(i,1);
}
}
else
{
scanf("%d%d",&a,&b);
ans=getSum(b)-getSum(a-1);
printf("%d\n",ans);
}
}
return 0;
}