Loading [MathJax]/extensions/tex2jax.js

LibreOJ 2187:「SHOI2014」三叉神经树 – 题解

主要思路

先建好树,大概思考一下应该可以推导出:倍增找标记点,然后根到区间修改。然而正解也是这样写,只不过细节有点多,我在这里提一下:回答询问\(x\)时,先把他父亲提到根,然后找最近的点;找到了就把深度大的全部打标记反过来。

代码

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// LOJ2187.cpp
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = (5e5 + 200) * 3;
int ch[MAX_N][2], fa[MAX_N], siz[MAX_N], idx[MAX_N][3], tag[MAX_N], sum[MAX_N], val[MAX_N];
int head[MAX_N], current, n, q;
struct edge
{
int to, nxt;
} edges[MAX_N << 1];
void addpath(int src, int dst)
{
edges[current].to = dst, edges[current].nxt = head[src];
head[src] = current++;
}
#define lson (ch[p][0])
#define rson (ch[p][1])
// LCT;
int check(int p) { return ch[fa[p]][1] == p; }
bool isRoot(int p) { return ch[fa[p]][1] != p && ch[fa[p]][0] != p; }
void pushup(int p)
{
siz[p] = siz[lson] + siz[rson] + 1;
idx[p][1] = idx[rson][1], idx[p][2] = idx[rson][2];
if (!idx[p][1])
{
if (sum[p] != 1)
idx[p][1] = p;
else
idx[p][1] = idx[lson][1];
}
if (!idx[p][2])
{
if (sum[p] != 2)
idx[p][2] = p;
else
idx[p][2] = idx[lson][2];
}
}
void sumup(int p, int value)
{
sum[p] += value, val[p] = sum[p] > 1;
swap(idx[p][1], idx[p][2]), tag[p] += value;
}
void pushdown(int p)
{
if (tag[p] != 0)
{
if (lson)
sumup(lson, tag[p]);
if (rson)
sumup(rson, tag[p]);
tag[p] = 0;
}
}
void rotate(int x)
{
int y = fa[x], z = fa[y], dir = check(x), w = ch[x][dir ^ 1];
fa[x] = z;
if (!isRoot(y))
ch[z][check(y)] = x;
fa[y] = x, ch[x][dir ^ 1] = y;
fa[w] = y, ch[y][dir] = w;
pushup(y), pushup(x);
}
void update(int p)
{
if (!isRoot(p))
update(fa[p]);
pushdown(p);
}
void splay(int p)
{
update(p);
for (int fat = fa[p]; fat = fa[p], !isRoot(p); rotate(p))
if (!isRoot(fat))
rotate(fat == p ? fat : p);
pushup(p);
}
void access(int p)
{
for (int pre = 0; p != 0; pre = p, p = fa[p])
splay(p), rson = pre, pushup(p);
}
#undef rson
#undef lson
void dfs(int u)
{
for (int i = head[u]; i != -1; i = edges[i].nxt)
dfs(edges[i].to), sum[u] += val[edges[i].to];
if (u <= n)
val[u] = sum[u] > 1;
}
int main()
{
memset(head, -1, sizeof(head));
scanf("%d", &n);
for (int i = 1, x1, x2, x3; i <= n; i++)
{
scanf("%d%d%d", &x1, &x2, &x3), addpath(i, x1), addpath(i, x2), addpath(i, x3);
fa[x1] = fa[x2] = fa[x3] = i;
}
for (int i = n + 1; i <= 3 * n + 1; i++)
scanf("%d", &val[i]);
dfs(1), scanf("%d", &q);
int finalStat = val[1];
while (q--)
{
int x, fat;
scanf("%d", &x), fat = fa[x];
int targetDelta = val[x] ? -1 : 1;
access(fat), splay(fat);
int mid = idx[fat][val[x] ? 2 : 1];
if (mid != 0)
{
splay(mid), sumup(ch[mid][1], targetDelta), pushup(ch[mid][1]);
sum[mid] += targetDelta, val[mid] = sum[mid] > 1;
pushup(mid);
}
else
// passthrough;
finalStat ^= 1, sumup(fat, targetDelta), pushup(fat);
val[x] ^= 1, printf("%d\n", finalStat);
}
return 0;
}
// LOJ2187.cpp #include <bits/stdc++.h> using namespace std; const int MAX_N = (5e5 + 200) * 3; int ch[MAX_N][2], fa[MAX_N], siz[MAX_N], idx[MAX_N][3], tag[MAX_N], sum[MAX_N], val[MAX_N]; int head[MAX_N], current, n, q; struct edge { int to, nxt; } edges[MAX_N << 1]; void addpath(int src, int dst) { edges[current].to = dst, edges[current].nxt = head[src]; head[src] = current++; } #define lson (ch[p][0]) #define rson (ch[p][1]) // LCT; int check(int p) { return ch[fa[p]][1] == p; } bool isRoot(int p) { return ch[fa[p]][1] != p && ch[fa[p]][0] != p; } void pushup(int p) { siz[p] = siz[lson] + siz[rson] + 1; idx[p][1] = idx[rson][1], idx[p][2] = idx[rson][2]; if (!idx[p][1]) { if (sum[p] != 1) idx[p][1] = p; else idx[p][1] = idx[lson][1]; } if (!idx[p][2]) { if (sum[p] != 2) idx[p][2] = p; else idx[p][2] = idx[lson][2]; } } void sumup(int p, int value) { sum[p] += value, val[p] = sum[p] > 1; swap(idx[p][1], idx[p][2]), tag[p] += value; } void pushdown(int p) { if (tag[p] != 0) { if (lson) sumup(lson, tag[p]); if (rson) sumup(rson, tag[p]); tag[p] = 0; } } void rotate(int x) { int y = fa[x], z = fa[y], dir = check(x), w = ch[x][dir ^ 1]; fa[x] = z; if (!isRoot(y)) ch[z][check(y)] = x; fa[y] = x, ch[x][dir ^ 1] = y; fa[w] = y, ch[y][dir] = w; pushup(y), pushup(x); } void update(int p) { if (!isRoot(p)) update(fa[p]); pushdown(p); } void splay(int p) { update(p); for (int fat = fa[p]; fat = fa[p], !isRoot(p); rotate(p)) if (!isRoot(fat)) rotate(fat == p ? fat : p); pushup(p); } void access(int p) { for (int pre = 0; p != 0; pre = p, p = fa[p]) splay(p), rson = pre, pushup(p); } #undef rson #undef lson void dfs(int u) { for (int i = head[u]; i != -1; i = edges[i].nxt) dfs(edges[i].to), sum[u] += val[edges[i].to]; if (u <= n) val[u] = sum[u] > 1; } int main() { memset(head, -1, sizeof(head)); scanf("%d", &n); for (int i = 1, x1, x2, x3; i <= n; i++) { scanf("%d%d%d", &x1, &x2, &x3), addpath(i, x1), addpath(i, x2), addpath(i, x3); fa[x1] = fa[x2] = fa[x3] = i; } for (int i = n + 1; i <= 3 * n + 1; i++) scanf("%d", &val[i]); dfs(1), scanf("%d", &q); int finalStat = val[1]; while (q--) { int x, fat; scanf("%d", &x), fat = fa[x]; int targetDelta = val[x] ? -1 : 1; access(fat), splay(fat); int mid = idx[fat][val[x] ? 2 : 1]; if (mid != 0) { splay(mid), sumup(ch[mid][1], targetDelta), pushup(ch[mid][1]); sum[mid] += targetDelta, val[mid] = sum[mid] > 1; pushup(mid); } else // passthrough; finalStat ^= 1, sumup(fat, targetDelta), pushup(fat); val[x] ^= 1, printf("%d\n", finalStat); } return 0; }
// LOJ2187.cpp
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = (5e5 + 200) * 3;

int ch[MAX_N][2], fa[MAX_N], siz[MAX_N], idx[MAX_N][3], tag[MAX_N], sum[MAX_N], val[MAX_N];
int head[MAX_N], current, n, q;

struct edge
{
    int to, nxt;
} edges[MAX_N << 1];

void addpath(int src, int dst)
{
    edges[current].to = dst, edges[current].nxt = head[src];
    head[src] = current++;
}

#define lson (ch[p][0])
#define rson (ch[p][1])

// LCT;

int check(int p) { return ch[fa[p]][1] == p; }

bool isRoot(int p) { return ch[fa[p]][1] != p && ch[fa[p]][0] != p; }

void pushup(int p)
{
    siz[p] = siz[lson] + siz[rson] + 1;
    idx[p][1] = idx[rson][1], idx[p][2] = idx[rson][2];
    if (!idx[p][1])
    {
        if (sum[p] != 1)
            idx[p][1] = p;
        else
            idx[p][1] = idx[lson][1];
    }
    if (!idx[p][2])
    {
        if (sum[p] != 2)
            idx[p][2] = p;
        else
            idx[p][2] = idx[lson][2];
    }
}

void sumup(int p, int value)
{
    sum[p] += value, val[p] = sum[p] > 1;
    swap(idx[p][1], idx[p][2]), tag[p] += value;
}

void pushdown(int p)
{
    if (tag[p] != 0)
    {
        if (lson)
            sumup(lson, tag[p]);
        if (rson)
            sumup(rson, tag[p]);
        tag[p] = 0;
    }
}

void rotate(int x)
{
    int y = fa[x], z = fa[y], dir = check(x), w = ch[x][dir ^ 1];
    fa[x] = z;
    if (!isRoot(y))
        ch[z][check(y)] = x;
    fa[y] = x, ch[x][dir ^ 1] = y;
    fa[w] = y, ch[y][dir] = w;
    pushup(y), pushup(x);
}

void update(int p)
{
    if (!isRoot(p))
        update(fa[p]);
    pushdown(p);
}

void splay(int p)
{
    update(p);
    for (int fat = fa[p]; fat = fa[p], !isRoot(p); rotate(p))
        if (!isRoot(fat))
            rotate(fat == p ? fat : p);
    pushup(p);
}

void access(int p)
{
    for (int pre = 0; p != 0; pre = p, p = fa[p])
        splay(p), rson = pre, pushup(p);
}

#undef rson
#undef lson

void dfs(int u)
{
    for (int i = head[u]; i != -1; i = edges[i].nxt)
        dfs(edges[i].to), sum[u] += val[edges[i].to];
    if (u <= n)
        val[u] = sum[u] > 1;
}

int main()
{
    memset(head, -1, sizeof(head));
    scanf("%d", &n);
    for (int i = 1, x1, x2, x3; i <= n; i++)
    {
        scanf("%d%d%d", &x1, &x2, &x3), addpath(i, x1), addpath(i, x2), addpath(i, x3);
        fa[x1] = fa[x2] = fa[x3] = i;
    }
    for (int i = n + 1; i <= 3 * n + 1; i++)
        scanf("%d", &val[i]);
    dfs(1), scanf("%d", &q);
    int finalStat = val[1];
    while (q--)
    {
        int x, fat;
        scanf("%d", &x), fat = fa[x];
        int targetDelta = val[x] ? -1 : 1;
        access(fat), splay(fat);
        int mid = idx[fat][val[x] ? 2 : 1];
        if (mid != 0)
        {
            splay(mid), sumup(ch[mid][1], targetDelta), pushup(ch[mid][1]);
            sum[mid] += targetDelta, val[mid] = sum[mid] > 1;
            pushup(mid);
        }
        else
            // passthrough;
            finalStat ^= 1, sumup(fat, targetDelta), pushup(fat);
        val[x] ^= 1, printf("%d\n", finalStat);
    }
    return 0;
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *