zoukankan      html  css  js  c++  java
  • Codeforces 794F. Leha and security system 线段树

    F. Leha and security system
     

    Bankopolis, the city you already know, finally got a new bank opened! Unfortunately, its security system is not yet working fine... Meanwhile hacker Leha arrived in Bankopolis and decided to test the system!

    Bank has n cells for clients' money. A sequence from n numbers a1, a2, ..., an describes the amount of money each client has. Leha wants to make requests to the database of the bank, finding out the total amount of money on some subsegments of the sequence and changing values of the sequence on some subsegments. Using a bug in the system, Leha can requests two types of queries to the database:

    • 1 l r x y denoting that Leha changes each digit x to digit y in each element of sequence ai, for which l ≤ i ≤ r is holds. For example, if we change in number 11984381 digit 8 to 4, we get 11944341. It's worth noting that Leha, in order to stay in the shadow, never changes digits in the database to 0, i.e. y ≠ 0.
    • 2 l r denoting that Leha asks to calculate and print the sum of such elements of sequence ai, for which l ≤ i ≤ r holds.

    As Leha is a white-hat hacker, he don't want to test this vulnerability on a real database. You are to write a similar database for Leha to test.

    Input

    The first line of input contains two integers n and q (1 ≤ n ≤ 105, 1 ≤ q ≤ 105) denoting amount of cells in the bank and total amount of queries respectively.

    The following line contains n integers a1, a2, ..., an (1 ≤ ai < 109) denoting the amount of money in each cell initially. These integers do not contain leading zeros.

    Each of the following q lines has one of the formats:

    • 1 l r x y (1 ≤ l ≤ r ≤ n0 ≤ x ≤ 9, 1 ≤ y ≤ 9), denoting Leha asks to change each digit x on digit y for each element ai of the sequence for which l ≤ i ≤ r holds;
    • 2 l r (1 ≤ l ≤ r ≤ n), denoting you have to calculate and print the sum of elements ai for which l ≤ i ≤ r holds.
    Output

    For each second type query print a single number denoting the required sum.

    Examples
    input
    5 5
    38 43 4 12 70
    1 1 3 4 8
    2 2 4
    1 4 5 0 8
    1 2 5 8 7
    2 1 5
    output
    103
    207
     
    Note

    Let's look at the example testcase.

    Initially the sequence is [38, 43, 4, 12, 70].

    After the first change each digit equal to 4 becomes 8 for each element with index in interval [1; 3]. Thus, the new sequence is [38, 83, 8, 12, 70].

    The answer for the first sum's query is the sum in the interval [2; 4], which equal 83 + 8 + 12 = 103, so the answer to this query is 103.

    The sequence becomes [38, 83, 8, 12, 78] after the second change and [38, 73, 7, 12, 77] after the third.

    The answer for the second sum's query is 38 + 73 + 7 + 12 + 77 = 207.

    题意:

      给你n个数

      操作1:l r x y,区间[l,r]内所有数,数位上为x的都转化为y

      操作2: l r 求区间和

    题解:

      线段树区间合并

      建立10颗线段树,分别表示数字0~9所代表的值

      将x转化为y也就是在将第x颗线段树区间[l,r]和减去,加到第y颗线段树上

      这里的延时操作有点小技巧

      每次push_down的时候保持每个点(0~9)指向唯一的另外一个点,这样再更新的时候才不会超时

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e18+1LL;
    const double Pi = acos(-1.0);
    const int N = 5e5+10, M = 1e3+20, mod = 1e9+7,inf = 2e9;
    
    LL sum[N][11],H[N],a[N],sum2[12];
    int lazy[N][11],vis[12];
    
    void push_down(int i,int ll,int rr) {
        if(ll == rr) return ;
    
        for(int j = 0; j < 10; ++j) vis[j] = lazy[ls][j], sum2[j] = sum[ls][j];
        for(int j = 0; j < 10; ++j) {
            if(lazy[i][j] != j) {
                for(int k = 0; k < 10; ++k) {
                    if(lazy[ls][k] == j) vis[k] = lazy[i][j];
                }
                sum2[lazy[i][j]] += sum[ls][j]; sum2[j] -= sum[ls][j];
            }
        }
        for(int j = 0; j < 10; ++j)
            lazy[ls][j] = vis[j], sum[ls][j] = sum2[j];
    
        for(int j = 0; j < 10; ++j) vis[j] = lazy[rs][j], sum2[j] = sum[rs][j];
        for(int j = 0; j < 10; ++j) {
            if(lazy[i][j] != j) {
                for(int k = 0; k < 10; ++k) {
                    if(lazy[rs][k] == j) vis[k] = lazy[i][j];
                }sum2[lazy[i][j]] += sum[rs][j]; sum2[j] -= sum[rs][j];
            }
        }
        for(int j = 0; j < 10; ++j)
            lazy[rs][j] = vis[j], sum[rs][j] = sum2[j];
    
        for(int j = 0; j < 10; ++j) lazy[i][j] = j;
    }
    
    void push_up(int i,int ll,int rr) {
        for(int j = 0; j <= 9; ++j) {
            sum[i][j] = sum[ls][j] + sum[rs][j];
        }
    }
    
    void build(int i,int ll,int rr) {
    
        for(int j = 0; j < 10; ++j) lazy[i][j] = j;
    
        if(ll == rr) {
            for(int j = 0; j < 10; ++j) sum[i][j]  =0;
            LL tmp = a[ll];
            for(int j = 1; j <= 12; ++j) {
                sum[i][tmp%10] += H[j-1];
                tmp/=10;
                if(tmp == 0) break;
            }
            return ;
        }
    
        build(ls,ll,mid); build(rs,mid+1,rr);
        push_up(i,ll,rr);
    }
    
    void update(int i,int ll,int rr,int x,int y,int f,int s) {
    
        push_down(i,ll,rr);
        if(ll == x && rr == y) {
            for(int j = 0; j <= 9; ++j)
            if(lazy[i][j] == f) {
                lazy[i][j] = s;
                sum[i][s] += sum[i][f];
                sum[i][f] = 0;
            }
            return ;
        }
        if(y <= mid) update(ls,ll,mid,x,y,f,s);
        else if(x > mid) update(rs,mid+1,rr,x,y,f,s);
        else {
    
            update(ls,ll,mid,x,mid,f,s);
            update(rs,mid+1,rr,mid+1,y,f,s);
    
        }
    
        push_up(i,ll,rr);
    
    }
    
    
    LL query(int i,int ll,int rr,int x,int y) {
        push_down(i,ll,rr);
        if(ll == x && rr == y) {
            LL ret = 0;
            for(int j = 1; j <= 9; ++j) {
                ret += 1LL*j*sum[i][j];
            }
            return ret;
        }
        if(y <= mid) return query(ls,ll,mid,x,y);
        else if(x > mid) return query(rs,mid+1,rr,x,y);
        else {
            return query(ls,ll,mid,x,mid)+query(rs,mid+1,rr,mid+1,y);
        }
        push_up(i,ll,rr);
    
    }
    
    int n,q;
    
    int main() {
    
        scanf("%d%d",&n,&q);
    
        for(int i = 1; i <= n; ++i) {
            scanf("%I64d",&a[i]);
        }
    
        H[0] = 1;
        for(int i = 1; i <= 13; ++i) H[i] = H[i-1]*10;
    
        build(1,1,n);
    
        for(int i = 1; i <= q; ++i) {
            int op,x,y,l,r;
            scanf("%d",&op);
            if(op == 1) {
                scanf("%d%d%d%d",&l,&r,&x,&y);
                if(x == y) continue;
                update(1,1,n,l,r,x,y);
            }
            else {
                scanf("%d%d",&l,&r);
                printf("%I64d
    ",query(1,1,n,l,r));
            }
        }
    
        return 0;
    }
  • 相关阅读:
    Linux 下的类似Windows下Everything的搜索工具
    windows和linux环境下制作U盘启动盘
    程序调试手段之gdb, vxworks shell
    LeetCode 1021. Remove Outermost Parentheses (删除最外层的括号)
    LeetCode 1047. Remove All Adjacent Duplicates In String (删除字符串中的所有相邻重复项)
    LeetCode 844. Backspace String Compare (比较含退格的字符串)
    LeetCode 860. Lemonade Change (柠檬水找零)
    LeetCode 1221. Split a String in Balanced Strings (分割平衡字符串)
    LeetCode 1046. Last Stone Weight (最后一块石头的重量 )
    LeetCode 746. Min Cost Climbing Stairs (使用最小花费爬楼梯)
  • 原文地址:https://www.cnblogs.com/zxhl/p/6852387.html
Copyright © 2011-2022 走看看