洛谷 P9358 [ICPC2022 Xi'an R] Bridge(Splay)

传送门

解题思路

把每个国家的城市看成一条链。
那么建桥操作相当于将两条链的某处断开,然后交换断点后面的部分。
查询操作就是从链首开始找到链尾属于哪个国家。
这些操作可以由Splay平衡树来维护。
相当于开n个平衡树。
但是总点数O(NM)会爆炸,所以我们考虑实际用到的点只有O(N+Q),所以每个点实际上代表着一段区间(初始状态为每一棵平衡树只有一个点1~m+1)。
在b处建桥操作时就是将一个[L,R]的点劈开,分成两个点[L,b],[b+1,R],然后将[L,b]点Splay到根,两个右儿子进行交换即可。
同时要用set维护b位置所属的区间的平衡树上的编号(比较琐碎 ,难写)。
调了好久qwq

AC代码

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
#include<ctime>
#include<stack>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!(c>='0'&&c<='9')) {if(c=='-') f=-1;c=getchar();}
	while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
	return x*f;
}
#define mp(a,b) make_pair(a,b)
#define pii pair<int,int>
const int maxn=2e5+5;
set<pii> s[maxn];
int rt[maxn],cnt,n,m,q;
struct node{
	int l,r,fa,son[2],rk,val;
}tr[maxn*4];
void rotate(int x){
	int y=tr[x].fa,z=tr[y].fa;
	int c=(tr[y].son[1]==x);
	tr[tr[x].son[!c]].fa=y;
	tr[y].fa=x;
	tr[x].fa=z;
	tr[y].son[c]=tr[x].son[!c];
	tr[x].son[!c]=y;
	if(z) tr[z].son[tr[z].son[1]==y]=x;
	tr[x].rk=tr[y].rk;
}
void splay(int x){
	while(tr[x].fa){
		int y=tr[x].fa,z=tr[y].fa;
		if(z) ((tr[y].son[0]==x)^(tr[z].son[0]==y))?rotate(x):rotate(y);
		rotate(x);
	}
	rt[tr[x].rk]=x;
}
void add(int r,int x){
	cnt++;
	
	tr[cnt].fa=0;
	tr[x].fa=cnt;
	
	tr[cnt].l=tr[x].l;
	tr[cnt].r=r;
	tr[x].l=r+1;
	
	tr[cnt].son[0]=tr[x].son[0];
	tr[tr[x].son[0]].fa=cnt;
	tr[x].son[0]=0;
	tr[cnt].son[1]=x;
	
	tr[cnt].rk=tr[x].rk;
	rt[tr[x].rk]=cnt;
	
	tr[cnt].val=tr[x].val;
}
void Swap(int x,int y){
	swap(tr[x].fa,tr[y].fa);
	swap(tr[x].rk,tr[y].rk);
	tr[tr[x].fa].son[1]=x;
	tr[tr[y].fa].son[1]=y;
}
int findMax(int x){
	while(tr[x].fa) x=tr[x].fa;
	while(tr[x].son[1]) x=tr[x].son[1];
	return x;
}
int main()
{
	n=read(),m=read()+1,q=read();
	for(int i=1;i<=n;i++){
		rt[i]=++cnt;
		tr[cnt].l=1;
		tr[cnt].r=m;
		tr[cnt].val=i;
		tr[cnt].rk=i;
		s[i].insert(mp(m,cnt));
	}
	while(q--){
		int tp=read();
		if(tp==1){
			int a=read(),b=read();
			auto it=s[a].lower_bound(mp(b,0));
			int x=(*it).second;
			auto it2=s[a+1].lower_bound(mp(b,0));
			int y=(*it2).second;
			splay(x);
			add(b,x);
			s[a].insert(mp(b,cnt));
			splay(y);
			add(b,y);
			s[a+1].insert(mp(b,cnt));
			Swap(x,y); 
		}else{
			int a=read();
			printf("%d\n",findMax(rt[a]));
		}
//		for(int i=1;i<=cnt;i++) printf("id:%d val:%d fa:%d l:%d r:%d rk:%d\n",i,tr[i].val,tr[i].fa,tr[i].l,tr[i].r,tr[i].rk);
	}
    return 0;
}
posted @ 2024-02-28 23:39  尹昱钦  阅读(9)  评论(0编辑  收藏  举报