BZOJ 4825 [Hnoi2017]单旋

题解:LCT维护Splay形态

Splay后发现只会有几个点发生变化,用LCT维护一下就可以了

在Splay中维护siz

还可以用Splay维护DFS序,旋转后DFS序不变,深度以子树为单位变化

天真的我以为直接模拟Splay可以A掉QWQ

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
const int maxn=100009;

int T;
map<int,int>ma;
int tfa[maxn],tch[maxn][2];

int root,nn;
int fa[maxn],ch[maxn][2],siz[maxn],rev[maxn];
inline int son(int x){
	if(ch[fa[x]][1]==x)return 1;
	else return 0;
}
inline void pushup(int x){
	siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
}
inline bool isroot(int x){
	return (ch[fa[x]][0]!=x)&&(ch[fa[x]][1]!=x);
}
inline void pushdown(int x){
	if(rev[x]){
		rev[ch[x][0]]^=1;
		rev[ch[x][1]]^=1;
		rev[x]^=1;
		swap(ch[x][0],ch[x][1]);
	}
}
void Downfa(int x){
	if(!isroot(x))Downfa(fa[x]);
	pushdown(x);
}

inline void Rotate(int x){
	int y=fa[x];
	int z=fa[y];
	int b=son(x),c=son(y);
	int a=ch[x][b^1];
	if(!isroot(y))ch[z][c]=x;
	fa[x]=z;
	if(a)fa[a]=y;
	ch[y][b]=a;
	fa[y]=x;ch[x][b^1]=y;
	pushup(y);pushup(x);
}

void Splay(int x){
	Downfa(x);
	while(!isroot(x)){
		int y=fa[x];
		if(isroot(y)){
			Rotate(x);
		}else{
			if(son(x)==son(y)){
				Rotate(y);Rotate(x);
			}else{
				Rotate(x);Rotate(x);
			}
		}
	}
}

void Access(int x){
	for(int t=0;x;t=x,x=fa[x]){
		Splay(x);ch[x][1]=t;pushup(x);
	}
}
void Makeroot(int x){
	Access(x);Splay(x);rev[x]^=1;
}
void Linkp(int x,int y){
	Makeroot(x);fa[x]=y;
}
void Cutp(int x,int y){
	Makeroot(x);Access(y);Splay(y);
	fa[ch[y][0]]=0;ch[y][0]=0;pushup(y);
}

int Getdep(int x){
	Access(x);Splay(x);return siz[x];
}

int main(){
	scanf("%d",&T);
	while(T--){
		if(root)Makeroot(root);
		int opty,x;
		scanf("%d",&opty);
		if(opty==1){
			scanf("%d",&x);
			ma[x]=++nn;siz[nn]=1;
			if(root==0){
				root=nn;
			}else{
				map<int,int>::iterator it1=ma.lower_bound(x);
				map<int,int>::iterator it2=ma.upper_bound(x);
				if(it1==ma.begin()){//只有后继
					Linkp(nn,it2->second);
					tfa[nn]=it2->second;
					tch[it2->second][0]=nn;
				}else if(it2==ma.end()){//只有前驱
					--it1;
					Linkp(nn,it1->second);
					tfa[nn]=it1->second;
					tch[it1->second][1]=nn;
				}else{
					--it1;
					int dep1=Getdep(it1->second);
					int dep2=Getdep(it2->second);
					if(dep1>dep2){
						Linkp(nn,it1->second);
						tfa[nn]=it1->second;
						tch[it1->second][1]=nn;
					}else{
						Linkp(nn,it2->second);
						tfa[nn]=it2->second;
						tch[it2->second][0]=nn;
					}
				}
			}
			printf("%d\n",Getdep(nn));
		}
		if(opty==4){
			map<int,int>::iterator it=ma.begin();
			int x=it->second;
			printf("%d\n",Getdep(x));
			if(x==root){
				root=tch[x][1];
				tfa[tch[x][1]]=0;
				if(tch[x][1])Cutp(tch[x][1],x);
			}else{
				Cutp(x,tfa[x]);
				tch[tfa[x]][0]=0;
				int y=tch[x][1];
				if(y){
					Cutp(x,y);
					Linkp(tfa[x],y);
					tfa[y]=tfa[x];
					tch[tfa[x]][0]=y;
				}
			}
			ma.erase(it->first);
		}
		if(opty==5){
			map<int,int>::iterator it=ma.end();--it;
			int x=it->second;
			printf("%d\n",Getdep(x));
			if(x==root){
				root=tch[x][0];
				tfa[tch[x][0]]=0;
				if(tch[x][0])Cutp(tch[x][0],x);
			}else{
				Cutp(x,tfa[x]);
				tch[tfa[x]][1]=0;
				int y=tch[x][0];
				if(y){
					Cutp(x,y);
					Linkp(tfa[x],y);
					tfa[y]=tfa[x];
					tch[tfa[x]][1]=y;
				}
			}
			ma.erase(it->first);
		}
		if(opty==2){
			map<int,int>::iterator it=ma.begin();
			int x=it->second;
			printf("%d\n",Getdep(x));
			if(x==root){
			}else{
				Cutp(x,tfa[x]);
				tch[tfa[x]][0]=0;
				int y=tch[x][1];
				if(y){
					Cutp(x,y);
					Linkp(tfa[x],y);
					tfa[y]=tfa[x];
					tch[tfa[x]][0]=y;
				}
				Linkp(root,x);
				tfa[x]=0;tch[x][1]=root;
				tfa[root]=x;root=x;
			}
		}
		if(opty==3){
			map<int,int>::iterator it=ma.end();--it;
			int x=it->second;
			printf("%d\n",Getdep(x));
			if(x==root){
			}else{
				Cutp(x,tfa[x]);
				tch[tfa[x]][1]=0;
				int y=tch[x][0];
				if(y){
					Cutp(x,y);
					Linkp(tfa[x],y);
					tfa[y]=tfa[x];
					tch[tfa[x]][1]=y;
				}
				Linkp(root,x);
				tfa[x]=0;tch[x][0]=root;
				tfa[root]=x;root=x;
			}
		}
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/zzyer/p/8454343.html

时间: 2024-10-28 08:47:27

BZOJ 4825 [Hnoi2017]单旋的相关文章

bzoj4825 [Hnoi2017]单旋

4825: [Hnoi2017]单旋 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 520  Solved: 247[Submit][Status][Discuss] Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据 结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必修技能.有一天,邪恶的"卡"带着 他的邪恶的"常数"

BZOJ4825:[HNOI2017]单旋

4825: [Hnoi2017]单旋 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 550  Solved: 258[Submit][Status][Discuss] Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据 结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必修技能.有一天,邪恶的“卡”带着 他的邪恶的“常数”来企图毁灭 H 国.“卡”给

【BZOJ4825】[Hnoi2017]单旋 线段树+set

[BZOJ4825][Hnoi2017]单旋 Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必修技能.有一天,邪恶的“卡”带着他的邪恶的“常数”来企图毁灭 H 国.“卡”给 H 国的人洗脑说,splay 如果写成单旋的,将会更快.“卡”称“单旋 splay”为“spaly”.虽说他说的很没道理,但还是有 H 国的人相信了,小 H 就是其中之一,s

[HNOI2017]单旋

标签:线段树+set 题解: 此题的标题为splay,所以我们可以排除这道题的正解是splay的可能性.然后我们发现只有最值的单旋,而且,三点一线不需要先旋转父亲.通过手玩我们可以发现,就是把最值直接移到最顶端作为根节点,然后其他的点以及他们之间的父子关系全部都没有变化.于是就只要求深度了. 我们发现,最小值,他没有左子树,而右子树在单旋之后深度不变(-1+1),而其他的点深度全部+1.如果再删掉根节点,全部的点深度-1.于是就可以使用线段树,维护每一个点的深度. 首先输入所有的操作,对于全部的

HNOI2017单旋

单旋 这道题做法贼多,LCT,splay,线段树什么的貌似都行. 像我这种渣渣只会线段树了(高级数据结构学了也不会用). 首先离线所有操作,因为不会有两个点值重复,所以直接离散. 一颗线段树来维护所有点的深度,并将所有值丢进\(set\)中. 插入操作,在set找到前驱后继,前驱没有右儿子就放前驱右儿子,否则放后继左儿子,同时用\(ch\)和\(fa\)假装模拟树的形态. 旋转操作,在\(set\)里找到节点,可以发现旋转操作该点儿子深度不变,其他点深度加一,处理一下父子关系,然后线段树修改区间

[AH2017/HNOI2017]单旋

题目描述 H国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了H国的必修技能.有一天,邪恶的"卡"带着他的邪恶的"常数"来企图毁灭H国."卡"给H国的人洗脑说,splay如果写成单旋的,将会更快."卡"称"单旋splay"为"spaly".虽说他说的很没道理,但还是有H国的人相信

[2017.11.29]BZOJ4825[Hnoi2017]单旋

1 #include<bits/stdc++.h> 2 #define M 100010 3 #define RG register 4 #define inf 0x3f3f3f3f 5 using namespace std; 6 bool rev[M]; 7 set<int> tr; 8 set<int>::iterator it; 9 int m,rt,tp,big,cnt,cur,dau,dep,loc,sml,sum,tmp,c[M],fa[M],sz[M],

AC日记——「HNOI2017」单旋 LiBreOJ 2018

#2018. 「HNOI2017」单旋 思路: set+线段树: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #define maxtree maxn<<2 int val[maxtree],tag[maxtree],L[maxtree],R[maxtree],mid[maxtree]; int op[maxn],ki[maxn],bi[maxn],cnt,size,n,ch[maxn]

[HNOI 2017]单旋

Description H 国是一个热爱写代码的国家,那里的人们很小去学校学习写各种各样的数据结构.伸展树(splay)是一种数据 结构,因为代码好写,功能多,效率高,掌握这种数据结构成为了 H 国的必修技能.有一天,邪恶的“卡”带着 他的邪恶的“常数”来企图毁灭 H 国.“卡”给 H 国的人洗脑说,splay 如果写成单旋的,将会更快.“卡”称 “单旋 splay”为“spaly”.虽说他说的很没道理,但还是有 H 国的人相信了,小 H 就是其中之一,spaly 马 上成为他的信仰. 而 H