HNOI2017 spaly题解

来源:互联网 发布:矩阵论教学视频百度云 编辑:程序博客网 时间:2024/06/05 00:43

终于调过了,决定把这份巨屎无比的冗长代码贴上来
解题思路:
主要在于发现两个题目的性质:
1.对于插入操作,插入的元素只可能作为他前驱的右儿子或者后继的左儿子
2.旋转最大最小值,并不会改变树的结构,实质上就是把要删除的那个元素直接提到根节点(模拟即可证明)

有了这两条性质,我们可以发现只需要维护这棵树的形态并能够在log内的复杂度求树上某个点的深度
于是我们就可以想到用LCT(有删除操作)。
恰好LCT又是以深度为key值建树,所以我们只需要再维护原树的父子关系,便于LCT的link-cut,这个可以用set维护(找前驱后继),然后每次相当于询问每个点到根节点的距离,又变成模板了

代码细节很多,还要注意这是一棵有根树,还要维护根节点是谁
代码:

#include<bits/stdc++.h>#define ll long long#define mm(a, b) memset(a, b, sizeof(a))#define For(i, a, b) for(int i = (a);i <= (b); ++i)#define rep(i, a, b) for(int i = (a);i >= (b); --i)#define gnn cerr << "GNN睡着了" << endl;using namespace std;const int inf = 1e9 + 1;int read(){    int sum = 0, fg = 1;    char c = getchar();    while(c < '0' || c > '9'){if(c == '-')fg = -1;c = getchar();}    while(c >='0' && c <='9')sum = (sum << 1) + (sum << 3) + c-'0', c = getchar();    return sum * fg;}const int maxn = 200010;void file(){#ifndef ONLINE_JUDGE    freopen("ai.in", "r", stdin);    freopen("ai.out", "w", stdout);#endif}map<int , int> q;int m, tree[maxn], val[maxn], ch[maxn][2], rev[maxn], cnt, fa[maxn];bool isroot(int h){return ch[fa[h]][0] != h && ch[fa[h]][1] != h;}void pushup(int h){tree[h] = 1; tree[h] +=  tree[ch[h][0]] + tree[ch[h][1]];}void pushdown(int h){    if(!rev[h]) return;    rev[h] = 0;    swap(ch[h][0], ch[h][1]);    if(ch[h][0]) rev[ch[h][0]] ^= 1;    if(ch[h][1]) rev[ch[h][1]] ^= 1;}void PUSHDOWN(int h){    if(!isroot(h)) PUSHDOWN(fa[h]);    pushdown(h);}void rotate(int h){    int father = fa[h], grandfa = fa[father];    bool w = (ch[father][1] == h);    fa[ch[h][w^1]] = father;    ch[father][w] = ch[h][w^1];    fa[father] = h;    ch[h][w^1] = father;    fa[h] = grandfa;    if(ch[grandfa][0] == father) ch[grandfa][0] = h;    else if(ch[grandfa][1] == father) ch[grandfa][1] = h;    pushup(father), pushup(h);}bool pd(int h){return ch[fa[h]][0] == h;}void splay(int h){    PUSHDOWN(h);    while(!isroot(h)){        if(!isroot(fa[h]) && pd(h) == pd(fa[h])) rotate(fa[h]);        rotate(h);    }}void access(int h){    int y = 0;    while(h){        splay(h);        ch[h][1] = y;        pushup(h);        y = h;        h = fa[h];    }}void makeroot(int h){    access(h);    splay(h);    rev[h] ^= 1;}void cut(int x,int y){    makeroot(x);    access(y);    splay(y);    fa[x] = ch[y][0] = 0;}void link(int x,int y){    makeroot(x);    fa[x] = y;}void Get(){    m = read();}int zf = 0, nowroot, truelyfa[maxn], truelych[maxn][2];int get_dep(int h){    makeroot(nowroot);    access(h);    splay(h);    return tree[h];}set<int> Set;set<int>::iterator it, other;int nowyuansu, flag = 0;void _Min(int type){    it = Set.begin();    int Min = *it;    int id = q[Min];    printf("%d\n", get_dep(id));    if(type == 1) nowyuansu = Min;    if(id == nowroot) {flag = 1; return;}    if(truelych[id][1]) cut(truelych[id][1], id);    if(truelyfa[id]){        cut(truelyfa[id], id);        int father = truelyfa[id];        truelych[father][0] = truelych[id][1];        if(truelych[id][1]){            truelyfa[truelych[id][1]] = father;            link(truelych[id][1], father);        }    }    truelyfa[id] = 0;    if(nowroot == id){        if(truelych[id][1]){            link(id, truelych[id][1]);            truelyfa[truelych[id][1]] = id;        }    }    else{        truelych[id][1] = nowroot;        truelyfa[nowroot] = id;        link(id, nowroot);    }    nowroot = id;    makeroot(nowroot);}void _Max(int type){    it = Set.end();    -- it;    int Max = *it;    int id = q[Max];    printf("%d\n", get_dep(id));    if(type == 1) nowyuansu = Max;    if(id == nowroot) {flag = 1; return;}    if(truelych[id][0]) cut(truelych[id][0], id);    if(truelyfa[id]){        cut(truelyfa[id], id);        int father = truelyfa[id];        truelych[father][1] = truelych[id][0];        if(truelych[id][0]){            truelyfa[truelych[id][0]] = father;            link(truelych[id][0], father);        }    }    truelyfa[id] = 0;    if(nowroot == id){        if(truelych[id][0]){            link(id, truelych[id][0]);            truelyfa[truelych[id][0]] = id;        }    }    else{        truelych[id][0] = nowroot;        truelyfa[nowroot] = id;        link(id, nowroot);    }    nowroot = id;    makeroot(nowroot);}void solve(){    while(m --){        int type = read();        if(type == 1){            int x = read();            ++ cnt;            q[x] = cnt;            zf ++;            if(zf == 1) nowroot = cnt;            int pre = inf;            it = Set.lower_bound(x);            if(it != Set.begin()) --it, pre = *it;            other = Set.upper_bound(x);            int suf = inf;            if(other != Set.end()) suf = *other;            Set.insert(x);            int ans = 1;            if(pre != inf && suf != inf){                int ans1 = get_dep(q[pre]), ans2 = get_dep(q[suf]);                makeroot(nowroot);                if(get_dep(q[pre]) < get_dep(q[suf])){                    fa[cnt] = q[suf];                    truelyfa[cnt] = q[suf];                    truelych[q[suf]][0] = cnt;                    ans = ans2 + 1;                }                else{                    fa[cnt] = q[pre];                    truelyfa[cnt] = q[pre];                    truelych[q[pre]][1] = cnt;                    ans = ans1 + 1;                }            }            else if(pre != inf){                int ans1 = get_dep(q[pre]);                makeroot(nowroot);                fa[cnt] = q[pre];                truelyfa[cnt] = q[pre];                truelych[q[pre]][1] = cnt;                ans = ans1 + 1;            }            else if(suf != inf){                int ans2 = get_dep(q[suf]);                makeroot(nowroot);                fa[cnt] = q[suf];                truelyfa[cnt] = q[suf];                truelych[q[suf]][0] = cnt;                ans = ans2 + 1;            }            printf("%d\n", ans);        }        else if(type == 2){            _Min(0);        }        else if(type == 3){            _Max(0);        }        else if(type == 4){            flag = 0;            _Min(1);            if(flag && zf != 1){                cut(nowroot, truelych[nowroot][1]);                truelyfa[truelych[nowroot][1]] = 0;                nowroot = truelych[nowroot][1];            }            else if(zf != 1){                cut(nowroot, truelych[nowroot][1]);                nowroot = truelych[nowroot][1];                truelyfa[nowroot] = 0;            }            -- zf;            makeroot(nowroot);            Set.erase(nowyuansu);        }        else{            flag = 0;            _Max(1);            if(flag && zf != 1){                cut(nowroot, truelych[nowroot][0]);                truelyfa[truelych[nowroot][0]] = 0;                nowroot = truelych[nowroot][0];            }            else if(zf != 1){                cut(nowroot, truelych[nowroot][0]);                nowroot = truelych[nowroot][0];                truelyfa[nowroot] = 0;            }            --zf;            makeroot(nowroot);            Set.erase(nowyuansu);        }    }}int main(){    file();    Get();    solve();    return 0;}
原创粉丝点击