insert里的一堆cout<<k;是调试用的。 实测样例第一个插入中tr[k].r=0;执行完后k出事了(1变成0了),除了第一行输出了个0以外其他都对了。有人帮一下吗
#include<iostream>
#include<cstdlib>
#include<cstdio>
using namespace std;
struct node
{
int l,r,n,c,p,s;
}tr[100001];
int root=1,tot=0;
inline void zig(int &k)
{
int y=tr[k].l;
tr[k].l=tr[y].r;
tr[y].r=k;
tr[y].s=tr[k].s;
tr[k].s=tr[tr[k].l].s+tr[tr[k].r].s+tr[k].c;
k=y;
}
inline void zag(int &k)
{
int y=tr[k].r;
tr[k].r=tr[y].l;
tr[y].l=k;
tr[y].s=tr[k].s;
tr[k].s=tr[tr[k].l].s+tr[tr[k].r].s+tr[k].c;
k=y;
}
void insert(int &k,int val)
{
if (!k)
{
cout<<k;
k=++tot; cout<<k;
tr[k].n=val; cout<<k;
tr[k].p=rand(); cout<<k;
tr[k].c=1; cout<<k;
tr[k].s=1; cout<<k;
tr[k].l=0; cout<<k;
tr[k].r=0; cout<<k<<endl;
return;
}
else tr[k].s++;
if (tr[k].n==val) tr[k].c++;
else if (tr[k].n>val)
{
insert(tr[k].l,val);
if (tr[k].p>tr[tr[k].l].p) zig(k);
}
else
{
insert(tr[k].r,val);
if (tr[k].p>tr[tr[k].r].p) zag(k);
}
}
void del(int &k,int val)
{
if (tr[k].n==val)
{
if (tr[k].c>1) tr[k].c--,tr[k].s--;
else if (!tr[k].l||!tr[k].r) k=tr[k].l+tr[k].r;
else if (tr[tr[k].l].p<tr[tr[k].r].p)
{
zig(k);del(k,val);
}
else
{
zag(k);del(k,val);
}
}
else
{
tr[k].s--;
if (tr[k].n>val) del(tr[k].l,val);
else del(tr[k].r,val);
}
}
inline int pred(int k)
{
int ans=-1e9,x=root;
while (x)
{
if (tr[x].n<=k) ans=tr[x].n,x=tr[x].r;
else x=tr[x].l;
}
return ans;
}
inline int succ(int k)
{
int ans=1e9,x=root;
while (x)
{
if (tr[x].n>=k) ans=tr[x].n,x=tr[x].l;
else x=tr[x].r;
}
return ans;
}
inline int Rank(int val)
{
int ans=0,x=root;
while (x)
{
if (val==tr[x].n) return ans+tr[tr[x].l].s+1;
if (val>tr[x].n) x=tr[x].r,ans+=tr[tr[x].l].s+tr[x].c;
else x=tr[x].l;
}
return ans;
}
inline int kth(int k)
{
int x=root;
while (x)
{
if (tr[tr[x].l].s<k&&tr[tr[x].l].s+tr[x].c>=k) return tr[x].n;
if (tr[tr[x].l].s>=k) x=tr[x].l;
else k-=tr[tr[x].l].s+tr[x].c,x=tr[x].r;
}
return 0;
}
inline int Min(int x,int y)
{
return x<y?x:y;
}
int main()
{
int n,x,y;
scanf("%d",&n);
while (n--)
{
scanf("%d%d",&x,&y);
switch(x)
{
case 1:insert(root,y);break;
case 2:del(root,y);break;
case 3:printf("%d\n",Rank(y));break;
case 4:printf("%d\n",kth(y));break;
case 5:printf("%d\n",pred(y));break;
case 6:printf("%d\n",succ(y));break;
}
}
return 0;
}