zoukankan      html  css  js  c++  java
  • 建立多个树状数组

    链接:https://www.nowcoder.com/acm/contest/112/D
    来源:牛客网

    题目描述

    一个只含数字的字符串,q次操作,每次操作将第i位数字改为x,每次操作后,统计长度在[l, r]之间且首数字大于尾数字的子串的个数。

    输入描述:

    第一行一个只含数字的字符串;
    第二行3个整数q, l, r;
    接下来q行,每行两个整数i, x。

    输出描述:

    输出q行,每行一个整数,表示长度在[l, r]之间且首数字大于尾数字的子串的个数。
    示例1

    输入

    585605
    2 2 4
    1 6
    4 2

    输出

    7
    8

    备注:

    设字符串长度为n则:
    1 <= n <= 100000;
    1 <= q <= 100000; 1 <= l <= r <= n; 1 <= i <= n; 0 <= x<= 9;


    思路分析 :
      对每一个数字建立树状数组,然后每次更新维护树状数组即可,注意边界的判断。
    有一个地方WA 哭我了要,就是每次修改后,我忘记了修改串上的字母。
    代码示例:
    #define ll long long
    const int maxn = 1e5+5;
    
    char s[maxn];
    int c[12][maxn];
    int lowbit(int x) {return x&(-x);}
    int len;
    
    void update(int num, int p){
        for(int i = p; i <= len; i += lowbit(i)){
            c[num][i]++;
        }       
    }
     
    void init(){
        for(int i = 1; i <= len; i++){
            update(s[i]-'0', i);
        }   
    }
     
    void update2(int num, int p){
        for(int i = p; i <= len; i += lowbit(i)){
            c[num][i]--;
        }
    }
     
    ll add(int x, int p){
        ll sum = 0;
        for(int i = p; i >= 1; i -= lowbit(i)){
            sum += 1ll*c[x][i];
        }
        return sum;
    }
     
    int main() {
        //freopen("in.txt", "r", stdin);
        //freopen("out.txt", "w", stdout);
        int q, l, r;
        int p, x;
         
        scanf("%s", s+1);
        len = strlen(s+1);
        init();
        cin >> q >> l >> r;
        ll ans = 0;
        
        for(int i = 1; i <= len; i++){
            for(int j = 0; j <= 9; j++){
                int b = i+r-1, a = i+l-1;
                if (a <= len && j < (s[i]-'0')) ans += 1ll*add(j, min(len, b))-1ll*add(j, a-1);
            }
        }
        
        for(int i = 1; i <= q; i++){
            scanf("%d%d", &p, &x);
            ll sum = 0;
            for(int j = 0; j <= 9; j++){
                int b = p+r-1, a = p+l-1;
                if (a <= len && j < (s[p]-'0')) sum += 1ll*add(j, min(len, b))-1ll*add(j, a-1);
                a = p-r+1, b = p-l+1;
                a = max(a, 1);
                if (b >= 1 && j > (s[p]-'0')) sum += 1ll*add(j, b)-1ll*add(j, a-1); 
            }    
            update2(s[p]-'0', p);
            update(x, p);
            ll sum2 = 0;
            for(int j = 0; j <= 9; j++){
                int b = p+r-1, a = p+l-1;
                if (a <= len && j < x) sum2 += 1ll*add(j, min(len, b))-1ll*add(j, a-1);
                a = p-r+1, b = p-l+1;
                a = max(a, 1);
                if (b >= 1 && j > x) sum2 += 1ll*add(j, b)-1ll*add(j, a-1);
            }
            ans = ans-sum+sum2;
            printf("%lld
    ", ans);
            s[p] = '0'+x;
        }
        return 0;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    javaweb学习2
    javaweb学习1
    Java学习17
    python 正则表达式
    python 常用库
    python 常用内置函数
    python 函数高级功能
    python 正则表达式findall
    tcpdump
    安卓软件学习进度_1
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/9029285.html
Copyright © 2011-2022 走看看