BZOJ4825 单旋

Posted 社会主义市场经济

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ4825 单旋相关的知识,希望对你有一定的参考价值。

分析:一道水题,去年考场发现了特点但是不会splay维护挂了,然后现在我写了个treap。

画一画图就可以解决这道题了,自己试一下。

 

代码如下:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 102000;
int m,xxx;

namespace Treap{
    struct spaly{int son[2],fa;}t[maxn];
    int sz[maxn],ch[maxn][2],num,SpalyRoot,Prs[maxn];
    int key[maxn],lazy[maxn],dep[maxn],data[maxn],root;
    void push_down(int now){
        dep[now] += lazy[now];
        lazy[ch[now][0]] += lazy[now]; lazy[ch[now][1]] += lazy[now];
        lazy[now] = 0;
    }
    int merge(int root1,int root2){
        if(!root1) return root2; if(!root2) return root1;
        if(lazy[root1]) push_down(root1); if(lazy[root2]) push_down(root2);
        if(key[root1] <= key[root2]){
            ch[root1][1] = merge(ch[root1][1],root2);
            Prs[ch[root1][1]] = root1;
            sz[root1] = sz[ch[root1][0]] + sz[ch[root1][1]] + 1;
            return root1;
        }else{
            ch[root2][0] = merge(root1,ch[root2][0]);
            Prs[ch[root2][0]] = root2;
            sz[root2] = sz[ch[root2][0]] + sz[ch[root2][1]] + 1;
            return root2;
        }
    }
    pair<int,int> split(int Node,int Len){
        if(Len == 0) return make_pair(0,Node);
        if(Node == 0) return make_pair(0,0);
        if(lazy[Node]) push_down(Node);
        if(sz[ch[Node][0]] >= Len){
            pair<int,int> Ans = split(ch[Node][0],Len);
            ch[Node][0] = Ans.second; Prs[Ans.second] = Node;
            Ans.second = Node; Prs[Ans.first] = 0;
            sz[Node] = sz[ch[Node][0]] + sz[ch[Node][1]] + 1;
            return Ans;
        }else{
            pair<int,int> Ans = split(ch[Node][1],Len-sz[ch[Node][0]]-1);
            ch[Node][1] = Ans.first; Prs[Ans.first] = Node;
            Ans.first = Node; Prs[Ans.second] = 0;
            sz[Node] = sz[ch[Node][0]] + sz[ch[Node][1]] + 1;
            return Ans;
        }
    }
    int get_rank(int Node,int Val){
        if(Node == 0) return 0;
        if(data[Node] > Val) return get_rank(ch[Node][0],Val);
        else return sz[ch[Node][0]]+1+get_rank(ch[Node][1],Val);
    }
    int get_Kth(int Node){
        stack<int> sta; int pts = Node;
        while(pts){sta.push(pts),pts = Prs[pts];}
        int Th = 0;
        while(!sta.empty()){
            int dat = sta.top();sta.pop();
            if(lazy[dat]) push_down(dat);
            if(!sta.empty()&&ch[dat][1] == sta.top()){
                Th += sz[ch[dat][0]] + 1;
            }
        }
        Th += sz[ch[Node][0]] + 1;
        return Th;
    }
}

namespace operation{
    using namespace Treap;
    int Insert(int Val){
        if(root == 0){
            root++;sz[root]=1;key[root]=rand();data[root]=Val;dep[root]=1;
            num++;SpalyRoot++;return dep[root];
        }
        num++;sz[num] = 1;key[num] = rand();data[num] = Val;
        int rk = get_rank(root,Val);
        pair<int,int> nowp = split(root,rk);
        int rt = nowp.first,lt = nowp.second;
        while(ch[rt][1]) {if(lazy[rt])push_down(rt); rt = ch[rt][1];}
        while(ch[lt][0]) {if(lazy[lt])push_down(lt); lt = ch[lt][0];}
        if(lazy[rt]&&rt) push_down(rt); if(lazy[lt]&&lt) push_down(lt);
        if(!t[rt].son[1] && rt != 0){
            t[rt].son[1] = num;t[num].fa = rt;dep[num] = dep[rt]+1;
        }else{
            t[lt].son[0] = num;t[num].fa = lt;dep[num] = dep[lt]+1;
        }
        root = merge(merge(nowp.first,num),nowp.second);
        return dep[num];
    }
    int Spaly(int Kind){ // 0 min,1 max
        int nowp = root;
        while(ch[nowp][Kind]){
            if(lazy[nowp])push_down(nowp); nowp=ch[nowp][Kind];
        }
        if(nowp == SpalyRoot){return 1;}
        int Son = t[nowp].son[Kind^1],Father = t[nowp].fa;
        t[nowp].son[Kind^1] = SpalyRoot; t[SpalyRoot].fa = nowp;
        SpalyRoot = nowp;t[nowp].fa = 0;int finalans;
        int Len = get_Kth(Father);
        t[Father].son[Kind] = Son; t[Son].fa = Father;
        if(Kind == 0){
            pair<int,int> Ans = split(root,Len-1);
            pair<int,int> Cut = split(Ans.first,1);
            lazy[Ans.second]++;
            if(lazy[Cut.first]) push_down(Cut.first);
            finalans = dep[nowp]; dep[Cut.first] = 1;
            root = merge(merge(Cut.first,Cut.second),Ans.second);
        }else{
            pair<int,int> Ans = split(root,Len);
            pair<int,int> Cut = split(Ans.second,sz[Ans.second]-1);
            lazy[Ans.first]++;
            if(lazy[Cut.second]) push_down(Cut.second);
            finalans = dep[nowp];dep[Cut.second] = 1;
            root = merge(Ans.first,merge(Cut.first,Cut.second));
        }
        return finalans;
    }
    int Erase(int Kind){//0 min 1 max
        int finalans = Spaly(Kind);
        int nowp = root;
        while(ch[nowp][Kind]){
            if(lazy[nowp])push_down(nowp); nowp=ch[nowp][Kind];
        }
        SpalyRoot = t[nowp].son[Kind^1];
        t[SpalyRoot].fa = 0;t[nowp].son[Kind^1] = 0;
        pair<int,int> Les = split(root,get_Kth(nowp));
        pair<int,int> Spt = split(Les.first,get_Kth(nowp)-1);
        root = merge(Spt.first,Les.second);
        if(root != 0) lazy[root]--;
        return finalans;
    }
}

void work(){
    for(int i=1;i<=m;i++){xxx=i;
        int opt,x; scanf("%d",&opt);
        if(opt == 2 || opt == 3) printf("%d\n",operation::Spaly(opt%2));
        else if(opt == 4 || opt == 5) printf("%d\n",operation::Erase(opt%2));
        else {scanf("%d",&x);printf("%d\n",operation::Insert(x));}
    }
}

int main(){
    srand(19260817);
    scanf("%d",&m);
    work();
    return 0;
}

 

以上是关于BZOJ4825 单旋的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4825 单旋

BZOJ4825[Hnoi2017]单旋 线段树+set

bzoj4825 [Hnoi2017]单旋

BZOJ 4825 [Hnoi2017]单旋

[2017.11.29]BZOJ4825[Hnoi2017]单旋

BZOJ4825HNOI2017单旋(Link-Cut Tree)