社区讨论

萌新求助LCT WA

P3203[HNOI2010] 弹飞绵羊参与者 2已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@locvgb09
此快照首次捕获于
2023/10/30 20:24
2 年前
此快照最后确认于
2023/11/05 06:55
2 年前
查看原帖
调教不出来
C
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int, int>
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
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 << 1) + (x << 3) + c - '0', c = getchar();
    return x * f;
}
struct LCT
{
#define ls son[pos][0]
#define rs son[pos][1]

    int fa[N], siz[N], cnt[N], val[N], root, tcnt;
    int son[N][2];
    int rev[N];
    void pushup(int pos)
    {
        siz[pos] = val[pos] + siz[ls] + siz[rs];
    }
    bool isroot(int pos)
    {
        return pos != son[fa[pos]][0] && pos != son[fa[pos]][1];
    }
    void addtag(int pos)
    {
        rev[pos] ^= 1;
        swap(son[pos][0], son[pos][1]);
    }
    void pushdown(int pos)
    {
        if (rev[pos])
        {
            if (son[pos][1])
                addtag(son[pos][1]);
            if (son[pos][0])
                addtag(son[pos][0]);
            rev[pos] = 0;
        }
    }

    bool isson(int pos) { return pos == son[fa[pos]][1]; }

    void conect(int x, int d, int y)
    {
        son[x][d] = y;
        fa[y] = x;
    }

    void rorate(int x)
    {
        int y = fa[x], z = fa[y], dx = isson(x), dy = isson(y);

        fa[x] = z;
        if (!isroot(y))
            son[z][dy] = x;
        //conect(z, dy, x);
        conect(y, dx, son[x][dx ^ 1]);
        conect(x, dx ^ 1, y);
        pushup(y), pushup(x);
    }
    int st[N];
    void splay(int x)
    {
        int top;
        st[top = 1] = x;
        int u = x;
        while (!isroot(u))
            u = fa[u], st[++top] = u;
        while (top)
            pushdown(st[top--]);
        while (!isroot(x))
        {
            int y = fa[x];
            if (isroot(y))
            {
                rorate(x);
            }
            else if (isson(x) == isson(y))
                rorate(y), rorate(x);
            else
                rorate(x), rorate(x);
        }
        pushup(x);
    }
    void access(int x)
    {
        for (int i = 0; x; i = x, x = fa[x])
        {
            splay(x), son[x][1] = i, pushup(x);
        }
    }
    void makeroot(int x)
    {
        access(x);
        splay(x);
        addtag(x); // access 之后将没有右子树。然后把x变成根,把下面都翻转,这样x就是最小的元素了。
    }
    // int findroot(int x)
    // {
    //     access(x), splay(x);
    //     while (son[x][0])
    //         pushdown(x), x = son[x][0];
    //     splay(x);
    //     return x;
    // }
    void split(int x, int y)
    {
        makeroot(x);
        access(y);
        splay(y);
    }
    bool link(int x, int y)
    {
        // cout << x << " " << y << endl;
        makeroot(x);
        // if (findroot(y) == x)
        //     return 0; //两点已经在同一子树中,再连边不合法
        fa[x] = y;
        return 1;
    }
    bool cut(int x, int y)
    {
        split(x, y);
        fa[x] = son[y][0] = 0;
        pushup(y);
        return 1;
    }

} t;

int a[N];
int main()
{
    // freopen("1.in", "r", stdin);
    // freopen("1.out", "w", stdout);

    int n = read();

    for (int i = 1; i <= n; i++)
    {
        t.val[i] = 1;
        a[i] = read();
        if (i + a[i] <= n)
            t.link(i, i + a[i]);
    }
    int m = read();
    for (int i = 1; i <= m; i++)
    {
        int op = read(), x = read();
        x++;
        //cout << i << "--" << endl;
        if (op == 1)
        {
            t.makeroot(x);
            printf("%d\n", t.siz[x]);
        }
        else
        {
            int k = read();
            if (x + a[x] <= n)
                t.cut(x, x + a[x]);
            a[x] = k;
            if (x + a[x] <= n)
                t.link(x, x + a[x]);
        }
    }
}

回复

2 条回复,欢迎继续交流。

正在加载回复...