codeforces 794F

Posted hugh-locke

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了codeforces 794F相关的知识,希望对你有一定的参考价值。

数列a由n个数字组成,下标从1到n,进行q次操作。操作有两种:1.将ai中的数字x改为y,i∈[l,r];2.求∑ai,i∈[l,r]。
比如,将11984381中的8改为4,就变为了11944341。再将4改为1,就变为了11911311。
1≤n≤105,1≤q≤105,1≤l≤r≤n,1≤ai≤109,0≤x≤9,1≤y≤9。
数据保证ai没有前导0。

不难想到按位建10颗线段树,存储每位数字为i的区间的贡献,最终答案为∑i * sum(i)

问题在于lazy标记的下放,放的不好比暴力算法还多一个log

一个很巧妙的方法是lazy[i]标记表示当前区间内的数位i全部变成lazy[i],那么pushdown的操作就是每次更新下层结点,然后将本层结点初始化,即lazy[i] = i的操作来删除下放标记,pushup就只需更新区间和即可。

总的来说 本题的难点为lazy标记不太好想 写起来似乎也不太好写

#include<bits/stdc++.h>
int read()
    int x = 0,f = 1;
    char c = getchar();
    while(c < 0 || c > 9)
        if(c == -) f = -1;
        c = getchar();
    
    while(c >= 0 && c <= 9)
        x = x * 10 + c - 0;
        c = getchar();
    
    return x * f;

#define LL long long
const int maxn = 1e5 + 10;
int N,M;
int a[maxn];
struct Tree
    LL sum[10];
    int to[10];
    void init()
        for(int i = 0 ; i < 10; i ++) sum[i] = 0;
    
tree[maxn << 2];
void Pushup(int t)
    tree[t].init();
    for(int i = 0 ; i < 10; i ++)
        tree[t].sum[tree[t << 1].to[i]] += tree[t << 1].sum[i];
        tree[t].sum[tree[t << 1 | 1].to[i]] += tree[t << 1 | 1].sum[i];
    

LL tmp[10];
void Pushdown(int t)
    for(int i = 0 ; i < 10; i ++)
        tree[t << 1].to[i] = tree[t].to[tree[t << 1].to[i]];
        tree[t << 1 | 1].to[i] = tree[t].to[tree[t << 1 | 1].to[i]];
    
    for(int i = 0 ; i < 10; i ++) tmp[i] = 0;
    for(int i = 0 ; i < 10; i ++) tmp[tree[t].to[i]] += tree[t].sum[i];
    for(int i = 0 ; i < 10; i ++) tree[t].sum[i] = tmp[i];
    for(int i = 0 ; i < 10; i ++) tree[t].to[i] = i;


void Build(int t,int l,int r)
    for(int i = 0 ; i < 10; i ++) tree[t].to[i] = i;
    if(l == r)
        LL b = 1;
        int x = a[l];
        while(x)
            tree[t].sum[(x % 10)] += b;
            b *= 10; x /= 10;
        
        return;
    
    int m = l + r >> 1;
    Build(t << 1,l,m); Build(t << 1 | 1,m + 1,r);
    Pushup(t);

void update(int t,int l,int r,int x,int y,int L,int R)
    int m = L + R >> 1;
    if(l <= L && R <= r)
        for(int i = 0 ; i <= 9; i ++) if(tree[t].to[i] == x) tree[t].to[i] = y;
        return;
    
    Pushdown(t);
    if(r <= m) update(t << 1,l,r,x,y,L,m);
    else if(l > m) update(t << 1 | 1,l,r,x,y,m + 1,R);
    else
        update(t << 1,l,m,x,y,L,m);
        update(t << 1 | 1,m + 1,r,x,y,m + 1,R);
    
    Pushup(t);

LL query(int t,int l,int r,int L,int R)
    int m = L + R >> 1;
    if(l <= L && R <= r)
        LL ans = 0;
        for(int i = 0 ; i <= 9; i ++) ans += tree[t].to[i] * tree[t].sum[i];
        return ans;
    
    Pushdown(t);
    if(r <= m) return query(t << 1,l,r,L,m);
    else if(l > m) return query(t << 1 |1,l,r,m + 1,R);
    return query(t << 1,l,m,L,m) + query(t << 1 | 1,m + 1,r,m + 1,R);

int main()
    scanf("%d%d",&N,&M);
    for(int i = 1; i <= N ; i ++) a[i] = read();
    Build(1,1,N);
    while(M--)
        int op = read(),l = read(),r = read();
        if(op == 1)
            int x = read(),y = read();
            update(1,l,r,x,y,1,N);
        else
            printf("%lld\n",query(1,l,r,1,N));
        
    
    return 0;

 

以上是关于codeforces 794F的主要内容,如果未能解决你的问题,请参考以下文章

Naming Company CodeForces - 794C

Codeforces_794(---)

CodeForces - 794C:Naming Company(博弈&简单贪心)

codeforces 794F

Codeforces 794F. Leha and security system 线段树

数据结构专题