• 【BZOJ4825】【HNOI2017】单旋(Link-Cut Tree)


    【BZOJ4825】【HNOI2017】单旋(Link-Cut Tree)

    题面

    题面太长,懒得粘过来

    题解

    既然题目让你写Spaly
    那就肯定不是正解
    这道题目,让你求的是最大/最小值的深度
    如果有LCT,答案就很容易求
    直接用LCT维护这棵Spaly试试。。。

    手玩发现,最大/最小值旋到根
    就是把它的儿子给父亲,
    然后root直接变成它的儿子
    它变成root
    于是乎,每次的操作之和两个点有关
    在LCT中维护点在Spaly上的父子关系
    这样后面四个操作就解决了问题

    第一个操作
    一个点显然要么接在前驱的右儿子,要么接在后继的左儿子
    那么,搞一个set求一求前驱后继
    很容易证明前驱的右儿子和后继的左儿子一定有且仅有一个为空
    直接接上去就行了

    然后,就是一堆的细节问题
    比如说,在删除的时候要特判已经是root的情况之类的
    细节比较多
    稍微注意点

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define MAX 200000
    inline int read()
    {
    	int x=0,t=1;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return x*t;
    }
    struct Node
    {
    	int ch[2],ff;
    	int rev;
    	int v,size;
    	int ls,rs,fa;
    }t[MAX];
    int S[MAX],top;
    bool isroot(int x){return t[t[x].ff].ch[0]!=x&&t[t[x].ff].ch[1]!=x;}
    void pushup(int x){t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+1;}
    void rotate(int x)
    {
    	int y=t[x].ff,z=t[y].ff;
    	int k=t[y].ch[1]==x;
    	if(!isroot(y))t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
    	t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y;
    	t[x].ch[k^1]=y;t[y].ff=x;
    	pushup(y);pushup(x);
    }
    void pushdown(int x)
    {
    	if(t[x].rev)
    	{
    		t[t[x].ch[0]].rev^=1;
    		t[t[x].ch[1]].rev^=1;
    		t[x].rev^=1;
    		swap(t[x].ch[0],t[x].ch[1]);
    	}
    }
    void Splay(int x)
    {
    	S[top=1]=x;
    	for(int i=x;!isroot(i);i=t[i].ff)S[++top]=t[i].ff;
    	while(top)pushdown(S[top--]);
    	while(!isroot(x))
    	{
    		int y=t[x].ff,z=t[y].ff;
    		if(!isroot(y))
    			(t[y].ch[1]==x)^(t[z].ch[1]==y)?rotate(x):rotate(y);
    		rotate(x);
    	}
    }
    void access(int x){for(int y=0;x;y=x,x=t[x].ff)Splay(x),t[x].ch[1]=y,pushup(x);}
    void makeroot(int x){access(x);Splay(x);t[x].rev^=1;}
    void split(int x,int y){makeroot(x);access(y);Splay(y);}
    void cut(int x,int y){split(x,y);t[y].ch[0]=t[x].ff=0;pushup(y);}
    void link(int x,int y){makeroot(x);t[x].ff=y;}
    int tot,root,m;
    map<int,int> M;
    set<int> Set;
    void insert(int x)
    {
    	int now=++tot;
    	M[x]=now;
    	t[tot].v=x;
    	if(Set.empty())
    	{
    		Set.insert(x);
    		root=now;
    		puts("1");
    		return;
    	}
    	set<int>::iterator tt=Set.upper_bound(x);
    	if(tt==Set.end()||t[M[*tt]].ls)
    	{
    		tt--;
    		int kk=M[*tt];
    		link(now,kk),t[kk].rs=now,t[now].fa=kk;
    	}
    	else
    	{
    		int kk=M[*tt];
    		link(now,kk),t[kk].ls=now,t[now].fa=kk;
    	}
    	Set.insert(x);
    	split(now,root);
    	printf("%d
    ",t[root].size);
    }
    void Splay_min()
    {
    	int x=M[*Set.begin()];
    	if(root==x){puts("1");return;}
    	split(x,root);
    	printf("%d
    ",t[root].size);
    	cut(x,t[x].fa);if(t[x].rs)cut(x,t[x].rs);
    	link(x,root);if(t[x].rs)link(t[x].fa,t[x].rs);
    	t[t[x].fa].ls=t[x].rs;if(t[x].rs)t[t[x].rs].fa=t[x].fa;
    	t[x].fa=0;t[root].fa=x;t[x].rs=root;
    	root=x;
    }
    void Splay_max()
    {
    	int x=M[*--Set.end()];
    	if(root==x){puts("1");return;}
    	split(x,root);
    	printf("%d
    ",t[root].size);
    	cut(x,t[x].fa);if(t[x].ls)cut(x,t[x].ls);
    	link(x,root);if(t[x].ls)link(t[x].ls,t[x].fa);
    	t[t[x].fa].rs=t[x].ls;if(t[x].ls)t[t[x].ls].fa=t[x].fa;
    	t[x].fa=0;t[root].fa=x;t[x].ls=root;
    	root=x;
    }
    void Del_min()
    {
    	int x=M[*Set.begin()];
    	if(root==x){puts("1");if(t[x].rs)cut(x,t[x].rs);t[t[x].rs].fa=0;root=t[x].rs;Set.erase(Set.begin());return;}
    	split(x,root);
    	printf("%d
    ",t[root].size);
    	cut(x,t[x].fa);if(t[x].rs)cut(x,t[x].rs);
    	if(t[x].rs)link(t[x].fa,t[x].rs);
    	t[t[x].fa].ls=t[x].rs;if(t[x].rs)t[t[x].rs].fa=t[x].fa;
    	Set.erase(Set.begin());
    }
    void Del_max()
    {
    	int x=M[*--Set.end()];
    	if(root==x){puts("1");if(t[x].ls)cut(x,t[x].ls);t[t[x].ls].fa=0;root=t[x].ls;Set.erase(--Set.end());return;}
    	split(x,root);
    	printf("%d
    ",t[root].size);
    	cut(x,t[x].fa);if(t[x].ls)cut(x,t[x].ls);
    	if(t[x].ls)link(t[x].ls,t[x].fa);
    	t[t[x].fa].rs=t[x].ls;if(t[x].ls)t[t[x].ls].fa=t[x].fa;
    	Set.erase(--Set.end());
    }
    int main()
    {
    	m=read();
    	while(m--)
    	{
    		int opt=read();
    		if(opt==1)insert(read());
    		else if(opt==2)Splay_min();
    		else if(opt==3)Splay_max();
    		else if(opt==4)Del_min();
    		else Del_max();
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    URL的JavaScript解决之道
    JavaScript中Date对象的几个扩展方法
    taobao open
    Linux操作系统的日志说明
    DG常用运维命令及常见问题解决
    oracle系统视图
    oracle 自动备份、恢复功能
    oracle队列
    spring学习笔记
    sql语句拾遗
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8148689.html
Copyright © 2020-2023  润新知