题意略。
开始想开一个三维的树状数组,但是一算空间不够,正解是离线操作,按位来计算,一共是10位,所以总共是扫10遍,第i遍只处理第i位的询问,
注意在修改后,要把当前这个位的值存下来(这就是cur数组的作用)!
#include<bits/stdc++.h> #define maxn 100005 using namespace std; struct op{ int kind,l,r,d,p,x,y; }; int BIT[10][maxn]; int a[maxn],T,N,M,tens[10],cur[maxn]; int ans[maxn]; char comd[10]; op store[maxn]; int lowbit(int k){ return k & -k; } void add(int digit,int pos,int val){ while(pos <= N){ BIT[digit][pos] += val; pos += lowbit(pos); } } int sum(int digit,int pos){ int ret = 0; while(pos > 0){ ret += BIT[digit][pos]; pos -= lowbit(pos); } return ret; } int main(){ tens[0] = 1; for(int i = 1;i < 10;++i) tens[i] = tens[i - 1] * 10; scanf("%d",&T); while(T--){ scanf("%d%d",&N,&M); memset(ans,-1,sizeof(ans)); for(int i = 1;i <= N;++i) scanf("%d",&a[i]); for(int i = 0;i < M;++i){ scanf("%s",comd); if(comd[0] == ‘Q‘){ store[i].kind = 0; scanf("%d%d%d%d",&store[i].l,&store[i].r,&store[i].d,&store[i].p); } else{ store[i].kind = 1; scanf("%d%d",&store[i].x,&store[i].y); } } for(int i = 1;i <= 10;++i){ memset(BIT,0,sizeof(BIT)); for(int j = 1;j <= N;++j){ add(a[j] % 10,j,1); cur[j] = a[j] % 10; } for(int j = 0;j < M;++j){ //printf("------\n"); if(store[j].kind == 0 && store[j].d == i){ ans[j] = sum(store[j].p,store[j].r) - sum(store[j].p,store[j].l - 1); } else if(store[j].kind == 1){ int x = store[j].x,y = store[j].y; add(cur[x],x,-1); add((y / tens[i - 1]) % 10,x,1); cur[x] = (y / tens[i - 1]) % 10; } } for(int j = 1;j <= N;++j) a[j] /= 10; } for(int i = 0;i < M;++i){ if(ans[i] == -1) continue; printf("%d\n",ans[i]); } } return 0; } /* 3 7 7 101 123 132 456 78 9 1001 Q 1 4 3 4 Q 1 7 2 0 S 1 401 Q 1 4 3 4 Q 1 7 1 1 S 6 999 Q 1 7 3 1 5 7 10 11 12 13 14 Q 1 5 2 1 Q 1 5 1 0 Q 1 5 1 1 Q 1 5 3 0 Q 1 5 3 1 S 1 100 Q 1 5 3 1 6 5 2147483647 2147483647 2147483647 2147483647 2147483647 2147483647 Q 1 5 1 7 Q 2 6 10 2 S 6 0 Q 1 7 1 0 Q 1 7 2 0 */