Codeforces 794 F-Leha and security system[線分樹-区間更新]【データ構造】


テーマリンク:http://codeforces.com/problemset/problem/794/F ————————————————————————————————F.Leha and security system time limit per test 2 seconds memory limit per test 512 megabytes inputstandard input out put put standard out Bankolis、the city you already know、finally got a new bank opened!Unfortunally、its security system is not yet working fine…Meanwhile hacker Leha arrived in Bankopolis and decided to test the system!
Bank has n cers for clients’money.A sequence from n numbers a 1,?a2,_;…,?andescribes the amount of money each clienthas.Lehants to makerequestst to the datatabase of thethe baininininininininininininininininininininininininine of of of of of of of of of babasesesestststststststststststststststststststststinininininininininininininininininininininininininininininininininininence on some subsegments.Using a bug in the system,レハcan requests two types of queries to the database:
1 l l l x x y denoting ththat Leha change s each digit x to digit y in each element of sequence ai、for which l?≦?ii?≦r r i s holds.For example、if we change i number ininberginininininininininininininininininininininininaber 11828282828282828282828282828282828282820.inininininininininininininininininininininininininininininininininininininininininininininininininindigit s in the database to 0、i.e.y.y?≠?0.2 l r denoting that Leha asks to cacacacacalate and print t he sum of such elemens of sequence a i、for which l̵?ii????̵̵?̵?̵̵̵̵̵̵?̵̵̵?̵̵̵̵̵̵simiardatabase for Leha to test.
Input The first line of input contains two integers n and q(1̵≦?nn?105,1̵̵q≦?105)denoting amount of cers thers bank bactures.
The follwing line contains n integersa 1,̵a2,̵…,?an(1?≤?ai̵)
Each of the followwing q lines has one of the formas:
1 l r x y(1̴≦?ll?≦?r?≦?n、0?≤?n、0????????̵̵̵???̵̵?̵̵̵?̵̵?;i̵≦̵rholds;2 l r(1̵≦̵l?≦r≦?n)、denoting you have to calculate and print the sum of elemens a i for which l?≦̵̵̵̵̵?̵
Examples input 5 38 43 4 12 7 1 3 4 4 8 2 4 1 4 5 0 8 1 5 5 5 8 7 2 1 5 output 103 207 input 5 5 5 5 5 6 6 6 6 9 1 3 3 2 1 2 2 1 3 1 5 5 1 1 4 4 9 2 1 5 output 111 1002 Note Let's look at the example.catese.cast。
Initially the sequence is[38,8201].
After the first change each digit equal to 4 becompes 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 103.
The sequence becompes[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のシーケンスには、二つの動作があります。
  • は、[l,r]のすべての数のうち、ビットxをy
  • に変更します。
  • 求[l,r]上所有数的和
  • 問題解決の考え方:
    それとも直接的な線分樹のメンテナンスを考慮して、各ノードは10個の情報を維持して、それぞれ0~9桁の和を数えて、同時に遅延標識を維持します。
    求和部分略、
    数桁の修正に対して、最大の問題はどのようにlazyを維持するかということです。
    ここでメンテナンスしているlazyは同じ10個ありますが、lazy[i]は次の数の中でiの桁が数桁のlazy[i]になります。
    問題は下に書いて伝えることです。どうすればいいですか?
    普通の表記と比べて複雑ですが、息子の価値を左右するものを先に変えて、lazyを統合していくだけです。
    コードを見たほうが分かりやすいです。
            pushdown 
        for(int i=0;i<10;i++)vis[i]=lazy[rt<<1][i],sum2[i]=sum[rt<<1][i];  //                
        for(int i=0;i<10;i++)if(lazy[rt][i]!=i){                           //
            for(int j=0;j<10;j++)if(lazy[rt<<1][j]==i) vis[j]=lazy[rt][i]; //    
            sum2[lazy[rt][i]]+=sum[rt<<1][i];                              //          
            sum2[i]-=sum[rt<<1][i];                                        //             ,       0
        }
        for(int i=0;i<10;i++) sum[rt<<1][i]=sum2[i],lazy[rt<<1][i]=vis[i];
    本題コードを添付します。————————————————————————————————————————————————————————————————————
    #include 
    typedef long long int LL;
    using namespace std;
    
    const int N = 1e5+7;
    /*****************************************/
    LL sum[N<<2][11],sum2[11],a[N];
    int lazy[N<<2][11],vis[11];
    
    void pushdown(int rt){
        for(int i=0;i<10;i++)vis[i]=lazy[rt<<1][i],sum2[i]=sum[rt<<1][i];
        for(int i=0;i<10;i++)if(lazy[rt][i]!=i){
            for(int j=0;j<10;j++)if(lazy[rt<<1][j]==i) vis[j]=lazy[rt][i];
            sum2[lazy[rt][i]]+=sum[rt<<1][i];
            sum2[i]-=sum[rt<<1][i];
        }
        for(int i=0;i<10;i++) sum[rt<<1][i]=sum2[i],lazy[rt<<1][i]=vis[i];
    
        for(int i=0;i<10;i++) vis[i]=lazy[rt<<1|1][i],sum2[i]=sum[rt<<1|1][i];
        for(int i=0;i<10;i++)if(lazy[rt][i]!=i){
            for(int j=0;j<10;j++)if(lazy[rt<<1|1][j]==i) vis[j]=lazy[rt][i];
            sum2[lazy[rt][i]]+=sum[rt<<1|1][i];
            sum2[i]-=sum[rt<<1|1][i];
        }
        for(int i=0;i<10;i++) sum[rt<<1|1][i]=sum2[i],lazy[rt<<1|1][i]=vis[i];
    
        for(int i=0;i<10;i++) lazy[rt][i] = i;
    }
    
    void pushup(int rt){
        for(int i=0;i<10;i++) sum[rt][i]=sum[rt<<1][i]+sum[rt<<1|1][i];
    }
    
    void build(int rt,int l,int r){
        for(int i=0;i<10;i++) sum[rt][i]=0;
        for(int i=0;i<10;i++)lazy[rt][i]=i;
        if(l==r){
            for(LL t=1;a[l];a[l]/=10,t*=10)
                sum[rt][a[l]%10]+=t;
            return ;
        }
        int m = r+l >> 1;
        build(rt<<1  ,l  ,m);
        build(rt<<1|1,m+1,r);
        pushup(rt);
    }
    
    void update(int rt,int l,int r,int L,int R,int x,int y){
        if(L<=l&&r<=R){
            for(int i=0;i<10;i++)if(lazy[rt][i]==x){
                sum[rt][y]+=sum[rt][x];
                sum[rt][x]=0;
                lazy[rt][i]=y;
            }
            return ;
        }
        pushdown(rt);
        int m = r+l >> 1;
        if(L<=m) update(rt<<1  ,l  ,m,L,R,x,y);
        if(R> m) update(rt<<1|1,m+1,r,L,R,x,y);
        pushup(rt);
    }
    
    LL query(int rt,int l,int r,int L,int R){
        if(L<=l&&r<=R){
            LL ans = 0;
            for(LL i=1;i<10;i++) ans+=sum[rt][i]*i;
            return ans;
        }
        pushdown(rt);
        int m = r+l >> 1;LL ans = 0;
        if(L<=m) ans += query(rt<<1  ,l  ,m,L,R);
        if(R> m) ans += query(rt<<1|1,m+1,r,L,R);
        pushup(rt);
        return ans;
    }
    
    int n,m;
    int main(){
        while(~scanf("%d%d",&n,&m)){
            for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
            build(1,1,n);
            int op,l,r,x,y;
            for(int i=1;i<=m;i++){
                scanf("%d%d%d",&op,&l,&r);
                if(1==op){
                    scanf("%d%d",&x,&y);
                    if(x==y) continue;
                    update(1,1,n,l,r,x,y);
                }
                else printf("%lld
    "
    ,query(1,1,n,l,r)); } } return 0; }