Codeforces 794 F Leha and security system(线段树+构造)

来源:互联网 发布:百雀羚vs欧莱雅 知乎 编辑:程序博客网 时间:2024/05/29 02:37

题目地址:http://codeforces.com/contest/794/problem/F
题意:给你n个数字和两种操作,分别为

  • 1 l r x y(l~r区间里的数字把每位如果是x的改为y)
  • 2 l r(查询l~r区间内的数的和)

思路:建10棵线段树,编号为0~9,代表的是每个数字在每个数中的权重,其他的和普通线段是一样,但是对于lazy的处理上有一个优化,因为每次访问到该节点的时候都是先进行过PushDown的所以每次都是初值,所以当多次改变的时候lazy的值是不会错的,但是有一个小优化,当当前节点的lazy的值是不是自己本身的,但是有是当前操作要修改的,那就直接改lazy就好了,因为权重是永远不会变的,只有拥有他的基数在变,在PushDown中修改的时候直接把不属于该基数的值按照lazy重新赋值就好了。

#include <iostream>#include <cstring>#include <string>#include <queue>#include <vector>#include <map>#include <set>#include <stack>#include <cmath>#include <cstdio>#include <algorithm>#define N 400010#define M 15000#define LL __int64#define inf 0x3f3f3f3f#define lson l,mid,ans<<1#define rson mid+1,r,ans<<1|1#define getMid (l+r)>>1#define movel ans<<1#define mover ans<<1|1using namespace std;const LL mod = 1e9 + 7;struct node {    LL sum;//记录的基数(基数*代表的数字=和),方便进行交换计算    int lazy;//记录与哪位数字交换}tree[10][N];LL H[N], nums[N], sum[12];int vis[12];struct Segment__Tree {    int x, y;    void pushUp(int ans) {        for (int i = 0; i <= 9; i++) {            tree[i][ans].sum = tree[i][movel].sum + tree[i][mover].sum;        }    }    void pushDown(int ans) {        for (int i = 0; i < 10; i++) {            vis[i] = tree[i][movel].lazy;            sum[i] = tree[i][movel].sum;        }        for (int i = 0; i < 10; i++) {            if (tree[i][ans].lazy != i) {//如果不是本身                for (int j = 0; j < 10; j++) {                    if (tree[j][movel].lazy == i) {                        vis[j] = tree[i][ans].lazy;                    }                }                sum[tree[i][ans].lazy] += tree[i][movel].sum;                sum[i]-= tree[i][movel].sum;            }        }        for (int i = 0; i < 10; i++) {            tree[i][movel].lazy = vis[i];            tree[i][movel].sum = sum[i];        }        for (int i = 0; i < 10; i++) {            vis[i] = tree[i][mover].lazy;            sum[i] = tree[i][mover].sum;        }        for (int i = 0; i < 10; i++) {            if (tree[i][ans].lazy != i) {//如果不是本身                for (int j = 0; j < 10; j++) {                    if (tree[j][mover].lazy == i) {                        vis[j] = tree[i][ans].lazy;                    }                }                sum[tree[i][ans].lazy] += tree[i][mover].sum;                sum[i] -= tree[i][mover].sum;            }        }        for (int i = 0; i < 10; i++) {            tree[i][mover].lazy = vis[i];            tree[i][mover].sum = sum[i];        }        for (int i = 0; i <= 9; i++) {            tree[i][ans].lazy = i;//初始化为本身        }    }    void build(int l, int r, int ans) {        for (int i = 0; i <= 9; i++) {            tree[i][ans].lazy = i;//初始化为本身        }        if (l == r) {            for (int i = 0; i <= 9; i++) {                tree[i][ans].sum = 0;            }            LL num = nums[l];            for (int i = 1; i <= 12; i++) {                tree[num % 10][ans].sum += H[i - 1];                num /= 10;                if (num == 0) {                    break;                }            }            return;        }        int mid = getMid;        build(lson);        build(rson);        pushUp(ans);    }    LL solve(int l, int r, int ans) {        if(l!=r) pushDown(ans);        if (l >= x&&r <= y) {            LL num = 0;            for (int i = 1; i <= 9; i++) {                num += 1LL * i*tree[i][ans].sum;            }            return num;        }        int mid = getMid;        if (mid<x) {            return solve(rson);        }        else if (mid >= y) {            return solve(lson);        }        else {            return solve(lson) + solve(rson);        }    }    void updata(int l, int r, int ans, int cnt, int num) {        if (l != r) pushDown(ans);        if (l >= x&&r <= y) {            for (int i = 0; i <= 9; i++) {                if (tree[i][ans].lazy == cnt) {                    tree[i][ans].lazy = num;//交换                    tree[num][ans].sum += tree[cnt][ans].sum;                    tree[cnt][ans].sum = 0;                }            }            return;        }        int mid = getMid;        if (mid<x) {            updata(rson, cnt, num);        }        else if (mid >= y) {            updata(lson, cnt, num);        }        else {            updata(lson, cnt, num);            updata(rson, cnt, num);        }        pushUp(ans);    }}segment__Tree;int main() {    cin.sync_with_stdio(false);    int n, q;    int a, b;    while (cin >> n >> q) {        for (int i = 1; i <= n; i++) {            cin >> nums[i];        }        H[0] = 1;        for (int i = 1; i <= 13; i++) {            H[i] = H[i - 1] * 10;//每位的倍数        }        segment__Tree.build(1, n, 1);        for (int i = 0; i < q; i++) {            cin >> a;            if (a == 1) {                cin >> segment__Tree.x >> segment__Tree.y >> a >> b;                if (a == b) {                    continue;                }                segment__Tree.updata(1, n, 1, a, b);            }            else {                cin >> segment__Tree.x >> segment__Tree.y;                cout << segment__Tree.solve(1, n, 1) << endl;            }        }    }    return 0;}
原创粉丝点击