題目鏈接: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;
}