救救孩子吧TAT
  • 板块学术版
  • 楼主Zigh_Wang
  • 当前回复2
  • 已保存回复2
  • 发布时间2022/6/28 21:05
  • 上次更新2023/10/27 22:23:39
查看原帖
救救孩子吧TAT
164883
Zigh_Wang楼主2022/6/28 21:05

LCT板子第11个点一直T

也不是死循环,就是很正经的T

调了一个下午了TAT

#include<bits/stdc++.h>
#define ls(x) son[x][0]
#define rs(x) son[x][1]
using namespace std;

const int MAXN = 1e5 + 5;

int inpt()
{
    int x = 0, f = 1;
    char ch;
    for(ch = getchar(); (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
    if(ch == '-'){
        f = -1;
        ch = getchar();
    }
    do{
        x = (x << 3) + (x << 1) + ch - '0';
        ch = getchar();
    }while(ch >= '0' && ch <= '9');
    return x * f;
}

int n, m;
int w[MAXN];

int sta[MAXN];

struct LinkCutTree {
    struct SplayTree {
        int fa[MAXN];
        int son[MAXN][2];
        int xum[MAXN];//xor_sum
        int tag[MAXN];

        bool IsRoot(int x) {//x为当前伸展树的根 
            return son[fa[x]][0] != x && son[fa[x]][1] != x;
        }

        void Update(int x) {
            xum[x] = xum[ls(x)] ^ xum[rs(x)] ^ w[x];
        }

        void PushDown(int x) {
            if(tag[x]) {
                swap(ls(x), rs(x));
                if(ls(x)) {
                    tag[ls(x)] ^= tag[x];
                }
                if(rs(x)) {
                    tag[rs(x)] ^= tag[x];
                } 
                tag[x] = 0;
            }
        }

        void PushAll(int x) {
            if(!IsRoot(x)) {
                PushAll(fa[x]);
            }
            PushDown(x);
        }

        void Rotate(int x) {
            int y = fa[x], z = fa[y];
            int c = (son[y][0] != x);//如果x是y的左儿子,则值为0,刚好代表左儿子 
            son[y][c] = son[x][!c];
            fa[son[x][!c]] = y;
            fa[x] = z;
            if(!IsRoot(y)) {
                son[z][son[z][0] != y] = x;
            }
            son[x][!c] = y;
            fa[y] = x;

            Update(y);
            Update(x);//此顺序必定不能换 
        }

        void Splay(int x) {//将x旋转成根 
//          PushAll(x);

            int t = x, tp = 0;
            sta[++tp] = t;
            while(!IsRoot(t)) {
                t = fa[t];
                sta[++tp] = t;
            }
            while(tp) {
                PushDown(sta[tp]);
                tp--;
            }

            while(!IsRoot(x)) {
                int y = fa[x], z = fa[y];
                int cx = (son[y][0] != x), cy = (son[z][0] != y);
                if(IsRoot(y)) {
                    Rotate(x);
                    return ;
                }
                if(cx == cy) {
                    Rotate(x);
                    Rotate(x);
                }else {
                    Rotate(y);
                    Rotate(x);
                }
            }
        }

        void Reverse(int x) {
            tag[x] ^= 1;
        }
    }tr;

    void Access(int x) {//打通x到根的实链 
        for(int t = 0; x; t = x, x = tr.fa[x]) {
            tr.Splay(x);
            tr.son[x][1] = t;
            tr.Update(x);
        }
    }

    void MakeRoot(int x) {//使x变成原树的根 
        Access(x);
        tr.Splay(x);
        tr.Reverse(x);
    }

    int FindRoot(int x) {//找出x所在实链的根 
        Access(x);
        tr.Splay(x);
        while(tr.son[x][0]) {
            x = tr.son[x][0];
        }
        tr.Splay(x);
        return x; 
    }

    void Split(int x, int y) {//分离出x,y之间的路径为一条实链 (以y为根) 
        MakeRoot(x);
        Access(y);
        tr.Splay(y);
    }

    void Link(int x, int y) {//连接x和 y  
//      if(FindRoot(x) == FindRoot(y)) return ;
        MakeRoot(x);
        if(FindRoot(y) == x) return ;
        tr.fa[x] = y;//建一条虚边 
    }

    void Cut(int x, int y) {//断开x, y 
        Split(x, y);
        if(tr.son[y][0] != x || tr.son[x][1]) return ;
        tr.son[y][0] = tr.fa[tr.son[y][0]] = 0;
//      tr.Update(y);
    } 

    int Ask(int x, int y) {
        Split(x, y);
//      tr.Update(y);
        return tr.xum[y];
    }

    void Change(int x, int v) {
        tr.Splay(x);
        w[x] = v;
//      tr.Update(x);
    }
}LCT;

int main()
{
    freopen("P3690_11.in", "r", stdin);
    freopen("My.out", "w", stdout);

    n = inpt(), m = inpt();
    for(int i = 1; i <= n; i++) {
        w[i] = inpt();
    }

    for(int i = 1; i <= m; i++) {
//      cout << i << endl;

        int opt = inpt();
        int x = inpt(), y = inpt();
        if(opt == 0) {
            printf("%d\n", LCT.Ask(x, y));
            continue;
        }
        if(opt == 1) {
            LCT.Link(x, y);
            continue;
        }
        if(opt == 2) {
            LCT.Cut(x, y);
            continue;
        }
        if(opt == 3) {
            LCT.Change(x, y);
            continue;
        }
    } 

    return 0;
}
2022/6/28 21:05
加载中...