洛谷 P1503 鬼子进村(平衡树)

传送门


解题思路

用平衡树维护摧毁的房屋。
摧毁等于insert,修复等于delete,询问等于查询前驱后继。
为了方便先扔进一个0点和n+1点。
注意查询时先进行判断当前房屋是否已经摧毁。

AC代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<bitset>
#include<stack>
using namespace std;
const int maxn=5e4+5;
int n,m,cnt,vis[maxn],rt;
struct node{
	int fa,val,son[2];
}tr[maxn];
int New(int val,int fa){
	cnt++;
	tr[cnt].fa=fa;
	tr[cnt].val=val;
	tr[cnt].son[0]=tr[cnt].son[1]=0;
	return cnt;
}
void Del(int x){
	tr[x].fa=tr[x].val=tr[x].son[0]=tr[x].son[1]=0;
}
void rotate(int x){
	int y=tr[x].fa,z=tr[y].fa;
	int c=(tr[y].son[1]==x);
	tr[x].fa=z;
	tr[y].fa=x;
	if(tr[x].son[!c]) tr[tr[x].son[!c]].fa=y;
	tr[y].son[c]=tr[x].son[!c];
	tr[x].son[!c]=y;
	if(z) tr[z].son[tr[z].son[1]==y]=x;
}
void splay(int x,int goal){
	if(x==goal) return;
	while(tr[x].fa!=goal){
		int y=tr[x].fa,z=tr[y].fa;
		if(z!=goal) ((tr[y].son[0]==x)^(tr[z].son[0]==y))?rotate(x):rotate(y);
		rotate(x);
	}
	if(!goal) rt=x;
}
void insert(int val){
	if(!rt){
		rt=New(val,0);
		return;
	}
	int x=rt;
	while(1){
		if(tr[x].son[tr[x].val<val]) x=tr[x].son[tr[x].val<val];
		else{
			tr[x].son[tr[x].val<val]=New(val,x);
			splay(cnt,0);
			return;
		}
	}
}
int pre(){
	int x=tr[rt].son[0];
	while(tr[x].son[1]) x=tr[x].son[1];
	return x;
}
int nxt(){
	int x=tr[rt].son[1];
	while(tr[x].son[0]) x=tr[x].son[0];
	return x;
}
void del(int x){
	splay(x,0);
	int rt=pre();
	splay(rt,0);
	splay(x,rt);
	tr[rt].son[1]=tr[x].son[1];
	if(tr[x].son[1]) tr[tr[x].son[1]].fa=rt;
	Del(x);
}
int main(){
	ios::sync_with_stdio(false);
	cin>>n>>m;
	insert(0);
	insert(n+1);
	for(int i=1;i<=m;i++){
		char op;cin>>op;
		if(op=='D'){
			int x;
			cin>>x;
			insert(x);
			vis[x]=1;
		}else{
			if(op=='R'){
				vis[tr[cnt].val]=0;
				del(cnt--);
			}else{
				int x;
				cin>>x;
				if(vis[x]) cout<<0<<endl;
				else insert(x),cout<<tr[nxt()].val-tr[pre()].val-1<<endl,del(cnt--);
			}
		}
	} 
	return 0;
}
posted @ 2021-11-07 14:56  尹昱钦  阅读(44)  评论(0编辑  收藏  举报