洛谷 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;
}