【bzoj3306】树

嗯没错就是树!
zkj大爷说是树剖 然而我再也不想写树剖了[省赛某题的阴影]
于是强行yy了下lct
开个multiset维护虚边链接的点的最小值
然后某个点的最小值就是splay里左右儿子的min和set的最小值
于是access的时候搞搞,换权值的时候记得要在set里面删掉原来的权值
同样是 O(nlog2n)
也不是很难写嘛 本来能1A的结果手抖CE了QAQ

#include <bits/stdc++.h>
using namespace std;
#define For(i,a,b) for(int i=a;i<=b;i++)
#define fore(i,u) for(int i=head[u];i;i=nxt[i])
#define lc ch[u][0]
#define rc ch[u][1]
#define maxn 100007

typedef int arr[maxn];

const int inf = 0x7fffffff;

inline int rd() {
    char c = getc(stdin);
    while (!isdigit(c)) c = getc(stdin) ; int x = c - '0';
    while (isdigit(c = getc(stdin))) x = x * 10 + c - '0';
    return x;
}

inline void upmin(int&a , int b) { if (a > b) a = b ; }

arr to , nxt , head , fa , mn , val , rv , sta;

int ch[maxn][2] , n , q , ett , top;

multiset<int> s[maxn];

inline void ins(int u , int v) {
    to[++ ett] = v , nxt[ett] = head[u] , head[u] = ett;
}

inline bool isrt(int u) { return (ch[fa[u]][0] != u) && (ch[fa[u]][1] != u) ; }

inline void mt(int u) { mn[u] = (*s[u].begin()) , upmin(mn[u] , min(lc ? mn[lc] : inf , rc ? mn[rc] : inf)) ; }

inline void rev(int u) { swap(lc , rc) , rv[lc] ^= 1 , rv[rc] ^= 1 , rv[u] = 0 ; }

inline void ps(int u) { if (u && rv[u]) rev(u) ; }

inline void rot(int u) {
    int f = fa[u] , g = fa[f] , l , r;
    l = (ch[f][1] == u) , r = l ^ 1;
    if (!isrt(f)) ch[g][ch[g][1] == f] = u;
    fa[u] = g , fa[f] = u;if (ch[u][r]) fa[ch[u][r]] = f;
    ch[f][l] = ch[u][r] , ch[u][r] = f;
    mt(f) , mt(u);
}

inline void clear(int u) {
    for(sta[top ++] = u;!isrt(u);u = fa[u]) sta[top ++] = fa[u];
    while (top) ps(sta[-- top]) ;
}

inline void splay(int u) {
    for(clear(u);!isrt(u);rot(u)) {
        int f = fa[u] , g = fa[f];
        if (!isrt(f)) rot(((ch[f][1] == u) ^ (ch[g][1] == f)) ? u : f);
    }
    mt(u);
}

void access(int u) {
    int v = u;
    for(int t = 0;u;t = u , u = fa[u]) {
        splay(u);
        if (rc) s[u].insert(mn[rc]);
        if (rc = t) s[u].erase(s[u].find(mn[t]));
    }
    splay(v);
}

void mkrt(int u) {
    access(u);
    if (rv[u] ^= 1) rev(u);
}

void dfs(int u) {
    s[u].insert(val[u]);
    fore(i , u) {
        int v = to[i];
        dfs(v) , fa[v] = u;
        s[u].insert(mn[v]);
    }
    mt(u);
}

void travel(int u) {
    for(multiset<int>::iterator it = s[u].begin();it != s[u].end();it ++) printf("%d " , *it);
    puts("\0");
}

int main() {
    #ifndef ONLINE_JUDGE
        freopen("data.txt" , "r" , stdin);
        freopen("data.out" , "w" , stdout);
    #endif
    memset(mn , 0x7f , sizeof mn);
    n = rd() , q = rd();
    For(i , 1 , n) {
        int x = rd() ; val[i] = rd();
        if (x) ins(x , i);
    }
    dfs(1);
    For(i , 1 , q) {
        char cmd[2];
        scanf("%s" , cmd);
        int u = rd();
        if (cmd[0] == 'V') {
            access(u);
            s[u].erase(s[u].find(val[u]));
            s[u].insert(val[u] = rd());
            mt(u);
        }
        else if (cmd[0] == 'E')
            mkrt(u);
        else if (cmd[0] == 'Q')
            access(u) , printf("%d\n" , *s[u].begin());
    }
    return 0;
}

你可能感兴趣的:(【bzoj3306】树)