萌新刚学 LCT,有点不懂的地方,求助各位神仙
查看原帖
萌新刚学 LCT,有点不懂的地方,求助各位神仙
63951
逃离地球楼主2021/2/25 11:31

我使用 LCT 实现这道题,设 lcol[x]rcol[x] 分别表示 xx 点的子树代表的区间最左边和最右边的颜色,tot[x] 表示 xx 点的子树代表的区间的颜色段数。

当我在做路径 xyx\to y 的修改操作时,我先 makeRoot(x), access(y), splay(y),然后再对 yy 点进行单点修改和打标记的操作。

问题就出在这里,我第一次实现的时候只修改了 yy 点的颜色和懒标记,而认为 lcol,rcol,tot 这些信息会在 pushUp 的时候被维护到,但是 WA 成了 0 分。

只有在单点修改时把 lcol,rcol,tot 全部修改才能对。

萌新刚学 LCT,想不清为什么,求助各位神仙qwq

附上我的代码:

#include <bits/stdc++.h>
using namespace std;
#define int long long
int re() {
    int ret = 0, f = 1;
    char ch = getchar();
    while (!isdigit(ch)) f = (ch == '-') ? -f : f, ch = getchar();
    while (isdigit(ch)) ret = ret * 10 + ch - '0', ch = getchar();
    return ret * f;
}

const int N = 2e5 + 5;
int n, m, ch[N][2], f[N], tot[N], col[N], lcol[N], rcol[N], laz[N], tag[N];

int get(int x) { return ch[f[x]][1] == x; }
bool isRoot(int x) { return (ch[f[x]][0] != x && ch[f[x]][1] != x); }
void pushUp(int x) {
    int lc = ch[x][0], rc = ch[x][1];
    lcol[x] = lc ? lcol[lc] : col[x], rcol[x] = rc ? rcol[rc] : col[x];
    if (lc && rc)
        tot[x] =
            tot[lc] + tot[rc] + 1 - (rcol[lc] == col[x]) - (lcol[rc] == col[x]);
    else if (lc)
        tot[x] = tot[lc] + 1 - (rcol[lc] == col[x]);
    else if (rc)
        tot[x] = tot[rc] + 1 - (lcol[rc] == col[x]);
    else
        tot[x] = 1;
}
void rev(int x) {
    tag[x] ^= 1, swap(ch[x][0], ch[x][1]), swap(lcol[x], rcol[x]);
}

// ------
void colour(int x, int c) {
    col[x] = lcol[x] = rcol[x] = laz[x] = c, tot[x] = 1;
} // 问题就在这里,为啥要修改这么多 qwq
// ------

void pushDown(int x) {
    if (tag[x]) rev(ch[x][0]), rev(ch[x][1]), tag[x] = 0;
    if (laz[x]) colour(ch[x][0], laz[x]), colour(ch[x][1], laz[x]), laz[x] = 0;
}
void update(int x) {
    if (!isRoot(x)) update(f[x]);
    pushDown(x);
}

void rotate(int x) {
    int fa = f[x], gfa = f[fa], r = get(x), rfa = get(fa);
    if (!isRoot(fa)) ch[gfa][rfa] = x;
    f[x] = gfa, ch[fa][r] = ch[x][r ^ 1], f[ch[x][r ^ 1]] = fa,
    ch[x][r ^ 1] = fa, f[fa] = x;
    pushUp(fa), pushUp(x);
}

void splay(int x) {
    update(x);
    for (int fa; fa = f[x], !isRoot(x); rotate(x))
        if (!isRoot(fa)) rotate(get(fa) == get(x) ? fa : x);
}

int access(int x) {
    int p;
    for (p = 0; x; p = x, x = f[x]) splay(x), ch[x][1] = p, pushUp(x);
    return p;
}

void makeRoot(int x) { x = access(x), rev(x); }

void link(int x, int y) { makeRoot(x), splay(x), f[x] = y; }

void split(int x, int y) { makeRoot(x), access(y), splay(y); }

void cut(int x, int y) { split(x, y), ch[y][0] = f[x] = 0; }

signed main() {
    n = re(), m = re();
    for (int i = 1; i <= n; ++i) col[i] = re();
    for (int i = 1, u, v; i < n; ++i) u = re(), v = re(), link(u, v);
    for (int i = 1; i <= m; ++i) {
        char op[5];
        scanf("%s", op);
        if (op[0] == 'C') {
            int a = re(), b = re(), c = re();
            split(a, b), colour(b, c);
        }
        if (op[0] == 'Q') {
            int a = re(), b = re();
            split(a, b), printf("%lld\n", tot[b]);
        }
    }
    return 0;
}

另外,血的教训,千万不要在读入数据结构题的操作符号的时候 scanf 一个 char!!!!!!!!

2021/2/25 11:31
加载中...