记录编号 416289 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 Toptree 最终得分 100
用户昵称 GravatarFoolMike 是否通过 通过
代码语言 C++ 运行时间 1.857 s
提交时间 2017-06-20 21:24:47 内存使用 6.60 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
using namespace __gnu_pbds;
const int N=1e5+10;
struct heap{
	__gnu_pbds::priority_queue<int,greater<int> > Q1,Q2;
	void push(int x){Q1.push(x);}
	void del(int x){Q2.push(x);}
	int top(){
		while (!Q2.empty()&&Q1.top()==Q2.top()) Q1.pop(),Q2.pop();
		return Q1.top();
	}
}H[N];
int fa[N],son[N][2],Min_v[N],Min_H[N],v[N];
int size[N],virt[N],vis[N],tag[N];
//H[x]表示x虚边所连接的子树的大小构成的堆 
//v[x]表示x的点权 
//Min_v[x]表示x所在splay子树中v的最小值 
//Min_H[x]表示x所在splay子树中H的最小值 
//virt[x]表示x虚边所连接的子树中子树大小和 
//size[x]表示x所在splay子树中v和virt的和 
bool root[N],rev[N];
#define lc son[x][0]
#define rc son[x][1]
void update(int x){
	Min_v[x]=v[x];
	Min_H[x]=H[x].top();
	size[x]=virt[x]+1;
	if (lc){
		Min_v[x]=min(Min_v[x],Min_v[lc]);
		Min_H[x]=min(Min_H[x],Min_H[lc]);
		size[x]+=size[lc];
	}
	if (rc){
		Min_v[x]=min(Min_v[x],Min_v[rc]);
		Min_H[x]=min(Min_H[x],Min_H[rc]);
		size[x]+=size[rc];
	}
}
void flip(int x){
	swap(lc,rc);
	rev[x]^=1;
}
void pushdown(int x){
	if (!x) return;
	if (rev[x]){
		if (lc) flip(lc);
		if (rc) flip(rc);
		rev[x]=0;
	}
	if (tag[x]){
		if (lc) vis[lc]=tag[lc]=tag[x];
		if (rc) vis[rc]=tag[rc]=tag[x];
		tag[x]=0;
	}
}
void rot(int x){
	int y=fa[x],z=fa[y];
	bool b=(x==son[y][1]);
	fa[son[y][b]=son[x][!b]]=y;
	fa[son[x][!b]=y]=x;
	fa[x]=z;
	if (son[z][0]==y) son[z][0]=x;else
	if (son[z][1]==y) son[z][1]=x;
	root[x]=root[y];root[y]=0;
	update(y);update(x);
}
void splay(int x){
	pushdown(x);
	for (;!root[x];rot(x)){
		int y=fa[x],z=fa[y];
		pushdown(z);pushdown(y);pushdown(x);
		if (!root[y]) rot((x==son[y][0])==(y==son[z][0])?y:x);
	}
}
void cut_r(int x){
	int y=rc;
	if (!y) return;
	rc=0;root[y]=1;
	virt[x]+=size[y];
	H[x].push(min(Min_v[y],Min_H[y]));
	update(x);
}
void link_r(int x,int y){
	virt[x]-=size[y];
	H[x].del(min(Min_v[y],Min_H[y]));
	root[rc=y]=0;
	update(x);
}
void access(int x){
	splay(x);
	cut_r(x);
	while (fa[x]){
		int y=fa[x];
		splay(y);
		cut_r(y);
		link_r(y,x);
		splay(x);
	}
}
void makeroot(int x){
	access(x);
	flip(x);
}
void link(int x,int y){
	makeroot(x);
	access(y);
	fa[x]=y;
	virt[y]+=size[x];
	H[y].push(min(Min_v[x],Min_H[x]));
	update(y);
}
void cut(int x,int y){
	makeroot(y);
	access(x);
	lc=fa[y]=0;root[y]=1;
	update(x);
}
int lca(int w,int x,int y){
	static int C=0;C++;
	makeroot(w);
	access(y);
	vis[y]=tag[y]=C;
	access(x);
	while (1){
		pushdown(x);
		if (rc&&vis[rc]==C) x=rc;else
		if (vis[x]==C) break;
		x=lc;
	}
	splay(x);
	return x;
}
int n,m;
int main()
{
	freopen("toptree.in","r",stdin);
	freopen("toptree.out","w",stdout);
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++){
		scanf("%d",&v[i]);
		H[i].push(1e9);
		root[i]=1;
		update(i);
	}
	while (m--){
		int tp,w,x,y;
		scanf("%d%d%d",&tp,&w,&x);
		if (tp==1) link(w,x);
		if (tp==2) cut(w,x);
		if (tp==3) access(w),v[w]=x,update(w);
		if (tp==4){
			makeroot(w);
			access(x);
			printf("%d\n",Min_v[x]);
		}
		if (tp==5){
			scanf("%d",&y);
			printf("%d\n",lca(w,x,y));
		}
		if (tp==6){
			makeroot(w);
			access(x);
			printf("%d\n",virt[x]+1);
		}
		if (tp==7){
			makeroot(w);
			access(x);
			printf("%d\n",min(v[x],H[x].top()));
		}
	}
	return 0;
}