http://acm.hdu.edu.cn/showproblem.php?pid=5057
分块,保存每个块中每位对应数字的和,复杂的是getmum,左右下标所在的块不能直接读取block数组,要重新自己计算。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; int a[100005],belong[100005],L[100005],R[100005],block[400][11][10],n,m; int ten[11] = {0,1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000}; void build() { int sizee = sqrt(n); int num = n/sizee; if(n%sizee) num++; for(int i = 1;i <= num;i++) { L[i] = (i-1)*sizee+1; R[i] = i*sizee; } for(int i = 1;i <= n;i++) belong[i] = (i-1)/sizee+1; for(int i = 1;i <= n;i++) { int temp = a[i]; for(int j = 1;j <= 10;j++) { block[belong[i]][j][temp%10]++; temp /= 10; } } } int getnum(int l,int r,int d,int p) { int ans = 0; if(belong[l] == belong[r]) { for(int i = l;i <= r;i++) { if((a[i]/ten[d])%10 == p) ans++; } return ans; } for(int i = belong[l]+1;i < belong[r];i++) ans += block[i][d][p]; for(int i = l;i <= R[belong[l]];i++) { if((a[i]/ten[d])%10 == p) ans++; } for(int i = L[belong[r]];i <= r;i++) { if((a[i]/ten[d])%10 == p) ans++; } return ans; } void update(int x,int y) { for(int i = 1;i <= 10;i++) { block[belong[x]][i][a[x]%10]--; a[x] /= 10; } a[x] = y; for(int i = 1;i <= 10;i++) { block[belong[x]][i][y%10]++; y /= 10; } } int main() { int T; scanf("%d",&T); while(T--) { memset(block,0,sizeof(block)); scanf("%d%d",&n,&m); for(int i = 1;i <= n;i++) scanf("%d",&a[i]); build(); char s[5]; while(m--) { scanf("%s",s); if(s[0] == 'S') { int x,y; scanf("%d%d",&x,&y); update(x,y); } else { int l,r,d,p; scanf("%d%d%d%d",&l,&r,&d,&p); printf("%d ",getnum(l,r,d,p)); } } } return 0; }