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
Data Constraint
50% 的数据满足N,M ≤ 103
100% 的数据满足1 ≤ N,M ≤ 105; 1 ≤ ai ≤ 104; 1 ≤ v ≤ 104
数据保证所有操作结束后ai ≤ 104。
Solution
本蒟蒻第一题手写的分块,感慨一下
把序列分成
n√
个块并维护每个块的桶。
对于一段(l,r)查询,暴力修改两端,中间的块就打标记
对于一段(l,r,v)修改,暴力修改两端,中间的块打标记
表示平衡树太jb难调了于是滚过来写点别的
Code
#include <stdio.h>
#include <string.h>
#include <math.h>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))
#define N 200005
#define M 20005
int rec[N],pos[N],add[N],a[N],s[N],e[N],t[501][M];
int n,m;
void read(int &x) {
x=0; int v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
x*=v;
}
void update(int x,int &y,int w) {
--t[x][y]; y+=w; ++t[x][y];
}
void prework() {
int st=1; rec[0]=0;
rec[++rec[0]]=4;
rec[++rec[0]]=7;
while (st<=rec[0]) {
int now=rec[st++];
if (now*10>=M) return;
rec[++rec[0]]=now*10+4;
rec[++rec[0]]=now*10+7;
}
}
void modify(int l,int r,int v) {
if (pos[l]==pos[r]) {
rep(i,l,r) update(pos[l],a[i],v);
} else {
rep(i,s[pos[r]],r) update(pos[r],a[i],v);
rep(i,l,e[pos[l]]) update(pos[l],a[i],v);
rep(i,pos[l]+1,pos[r]-1) add[i]+=v;
}
}
int query(int l,int r) {
int ret=0;
if (pos[l]==pos[r]) {
rep(i,l,r) {
rep(j,1,rec[0]) ret+=(a[i]+add[pos[l]])==rec[j];
}
} else {
rep(i,s[pos[r]],r) {
rep(j,1,rec[0]) ret+=(a[i]+add[pos[r]])==rec[j];
}
rep(i,l,e[pos[l]]) {
rep(j,1,rec[0]) ret+=(a[i]+add[pos[l]])==rec[j];
}
rep(i,pos[l]+1,pos[r]-1) {
rep(j,1,rec[0]) ret+=t[i][rec[j]-add[i]];
}
}
return ret;
}
int main(void) {
prework();
read(n); read(m);
int size=(int)(sqrt(n));
rep(i,1,n) {
read(a[i]);
pos[i]=(i-1)/size+1;
if (!s[pos[i]]) s[pos[i]]=i;
e[pos[i]]=i;
++t[pos[i]][a[i]];
}
while (m--) {
char opt[5];
int l,r,v;
scanf("%s",opt);
if (opt[0]=='c') {
read(l); read(r);
printf("%d\n",query(l,r));
} else {
read(l); read(r); read(v);
modify(l,r,v);
}
}
return 0;
}