正常写splay都会插入最大最小值,那么本题是否存在方法利用二叉搜索树的性质,采用一直找左/右儿子的策略,用跳过该点的方式直接删除?如果不行那么原因是什么?
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
#include<ctime>
//#include<bits/stdc++.h>
#define chp(x) (t[t[x].fa].ch[1]==x)
#define int long long
#define M 1000001
//#define inf 2147483647
using namespace std;
typedef int it;
inline it read()
{
int f=0,fu=1;
char c=getchar();
while(c<'0' || c>'9')
{
if(c=='-') fu=-1; c=getchar();
}
while(c>='0' && c<='9') {f=(f<<1)+(f<<3)+(c-'0'); c=getchar();}
return f*fu;
}
int n,m;
struct tree
{
int ch[2];
int w,c,fa;
}t[M];
int rt,tot,tmp;
inline void rotate(int x)
{
int y=t[x].fa,z=t[y].fa;
int p1=chp(x);
t[y].ch[p1]=t[x].ch[!p1];
t[t[x].ch[!p1]].fa=y;
if(z) t[z].ch[chp(y)]=x;
t[x].fa=z;
t[x].ch[!p1]=y;t[y].fa=x;
}
inline void splay(int x,int goal)
{
while(t[x].fa!=goal)
{
int y=t[x].fa,z=t[y].fa;
if(z)
if(chp(x)^chp(y)) rotate(x);
else rotate(y);
rotate(x);
}
if(goal==0) rt=x;
}
inline void insert(int x,int y)
{
int u=rt,nf=0;
while(u && t[u].w!=y)
{
nf=u;
u=t[u].ch[t[u].c<y];
}
if(u) return ;
else
{
u=++tot;
tmp++;
t[u].fa=nf;
if(nf) t[nf].ch[t[nf].c<y]=u;
t[u].w=x;
t[u].c=y;
}
splay(u,0);
}
inline void remote(int p)
{
if(tmp==0) return;
tmp--;
int u=rt;
while(t[u].ch[p])
u=t[u].ch[p];
t[t[u].fa].ch[p]=t[u].ch[!p];
t[t[u].ch[!p]].fa=t[u].fa;
t[u].fa=0;
}
queue<int>sp;
inline void outp()
{
int answ=0,ansc=0;
sp.push(rt);
while(!sp.empty())
{
int k=sp.front();
sp.pop();
answ+=t[k].w;
ansc+=t[k].c;
if(t[k].ch[1]) sp.push(t[k].ch[1]);
if(t[k].ch[0]) sp.push(t[k].ch[0]);
}
cout<<answ<<" "<<ansc;
}
signed main()
{
//freopen("P2073.in","r",stdin);
//freopen("P2073.out","w",stdout);
int op;
//insert(0,-inf);
//insert(0,inf);
while(1)
{
op=read();
if(op==-1) break;
if(op==1)
{
int x=read(),y=read();
insert(x,y);
}
if(op==2)
remote(1);
if(op==3)
remote(0);
}
outp();
return 0;
}