HDU 5057

题意略。

开始想开一个三维的树状数组,但是一算空间不够,正解是离线操作,按位来计算,一共是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("------
");
                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
",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
*/
原文地址:https://www.cnblogs.com/tiberius/p/8487061.html