重金5块钱求大佬帮忙看一下我的思路和代码哪里出现问题了?
查看原帖
重金5块钱求大佬帮忙看一下我的思路和代码哪里出现问题了?
291976
quanjun楼主2022/2/16 13:10

首先是看了一下官方题解:https://codeforces.com/blog/entry/99942

了解了一下可以对颜色 cc 开一个延迟标记 lazy[c]lazy[c](我代码实现的时候是用 tag[c]tag[c] 表示的,是一个意思)。

然后看了一下一位大佬的代码,有了一些启发。大佬的代码链接:https://codeforces.com/contest/1638/submission/146402136

主要这位大佬写的线段树的风格和我写的比较像,比较能接受一点。同时这位大佬的代码中关于的 addadd 值的处理也对我有很大的启发。启发在于:之前我 pushdown 的时候,不光是颜色传递下去,值也传递下去了,但是其实值可以保留在当前这个线段上,在查询的时候直接加上去就好了。

然后就是我 最困惑的地方:关于颜色的信息,正确的写法好像都是开了2个信息维护,但是我就只开了一个信息维护,不太清楚为什么。

比如上面大佬提交的代码,是开了两个数组维护颜色信息(col 和 cov),但是我是只开了一个数组(我代码中的 color 数组)。

所以我不知道我是哪里写错了。或者那个地方没有想明白。想请各位大佬帮我看一下我的代码,我将从所有解答中选出最好的代码并以 55 块钱作为酬谢。

下面是我的代码(也可点击 https://codeforces.com/contest/1638/submission/146582163 直接查看)

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6 + 5;
int n, q, color[maxn<<2];
long long add[maxn<<2], tag[maxn];
char op[11];

void push_up(int rt) {
    color[rt] = (color[rt<<1] == color[rt<<1|1]) ? color[rt<<1] : 0;
}

void push_down(int l, int r, int rt) {
    assert(l < r);
    if (color[rt]) {
        color[rt<<1] = color[rt<<1|1] = color[rt];
        color[rt] = 0;
    }
}

#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1

void build(int l, int r, int rt) {
    if (l == r) {
        color[rt] = 1;
        return;
    }
    int mid = (l + r) / 2;
    build(lson);
    build(rson);
    push_up(rt);
}

// 将 [L,R] 颜色变为 c
void update(int L, int R, int c, int l, int r, int rt) {
    if (L <= l && r <= R && color[rt]) {
        add[rt] += tag[color[rt]] - tag[c];
        color[rt] = c;
        return;
    }
    int mid = (l + r) / 2;
    push_down(l, r, rt);
    if (L <= mid) update(L, R, c, lson);
    if (R > mid) update(L, R, c, rson);
    push_up(rt);
}

// 将所有颜色为c的节点加上x
void addcolor(int c, int x) {
    tag[c] += x;
}

// 查询节点p的权值
long long query(int p, int l, int r, int rt) {
    if (l == r) {
        return add[rt] + tag[color[rt]];
    }
    push_down(l, r, rt);
    int mid = (l + r) / 2;
    return add[rt] + (p <= mid) ? query(p, lson) : query(p, rson);
}

int main() {
    scanf("%d%d", &n, &q);
    build(1, n, 1);
    while (q --) {
        scanf("%s", op);
        if (op[0] == 'C') {
            int l, r, c;
            scanf("%d%d%d", &l, &r, &c);
            update(l, r, c, 1, n, 1);
        }
        else if (op[0] == 'A') {
            int c, x;
            scanf("%d%d", &c, &x);
            addcolor(c, x);
        }
        else {
            int i;
            scanf("%d", &i);
            printf("%lld\n", query(i, 1, n, 1));
        }
    }
    return 0;
}

其中我用 color[rt] 表示 rt 节点对应的颜色信息,若 rt 维护的区间中所有节点颜色都是相同的一种颜色 c,则 color[rt] = c;否则(不是所有颜色都相同),则 color[rt] = 0

add[rt] 表示 rt 对应的区间累积加上的值。

我在 push_up 和 push_down 的时候更新的只有 color 的信息。

2022/2/16 13:10
加载中...