文章目录
R e s u l t Result Result
H y p e r l i n k Hyperlink Hyperlink
https://www.luogu.org/problemnew/show/P3369
D e s c r i p t i o n Description Description
写一种数据结构维护一些数据
包括插入,查找,删除,查找前驱,查找后继等
S o l u t i o n Solution Solution
好久之前扣 T r e a p Treap Treap过了这道题,后来坐我旁边那位大佬写了替罪羊树,赶紧去%%%,终于%到了这篇题解
C o d e Code Code
#include<cctype>
#include<cstdio>
#include<algorithm>
using namespace std;
struct node{int lson,rson,val,valid,total;bool ok;}t[2000001];
int nc[2000001],cz[2000001],root,lnc,lcz,buildwho,x,opt,m;
inline char Getchar()
{
static char buf[1000000],*p1=buf+1000000,*pend=buf+1000000;
if(p1==pend)
{
p1=buf; pend=buf+fread(buf,1,1000000,stdin);
if (pend==p1) return -1;
}
return *p1++;
}
inline long long read()
{
char c;int d=1;long long f=0;
while(c=Getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=Getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void write(register long long x)
{
if(x<0)putchar(45),x=-x;
if(x>9)write(x/10);
putchar(x%10+48);
return;
}
inline bool isbad(int k)//是否需要重构
{
if((double)t[k].valid*0.8<=(double)max(t[t[k].lson].valid,t[t[k].rson].valid)) return true;
return false;
}
void dfs(int k)//中序遍历
{
if(!k) return;
dfs(t[k].lson);
if(t[k].ok) cz[++lcz]=k;else nc[++lnc]=k;
dfs(t[k].rson);
return;
}
void build(int l,int r,int &k)//建树
{
int mid=l+r>>1;
k=cz[mid];
if(l==r)
{
t[k].lson=t[k].rson=0;
t[k].total=t[k].valid=1;
return;
}
if(l<mid) build(l,mid-1,t[k].lson);else t[k].lson=0;
build(mid+1,r,t[k].rson);
t[k].total=t[t[k].lson].total+t[t[k].rson].total+1;
t[k].valid=t[t[k].lson].valid+t[t[k].rson].valid+1;
return;
}
inline void rebuild(int &k)//重建
{
lcz=0;
dfs(k);
if(lcz) build(1,lcz,k);else k=0;
return;
}
inline int find_rank(int k)//查找k的排名
{
int now=root,ans=1;
while(now)
{
if(t[now].val>=k) now=t[now].lson;//在左边
else
{
ans+=t[t[now].lson].valid+t[now].ok;//往右边走要加上排名
now=t[now].rson;
}
}
return ans;
}
inline int find_kth(int k)//查找排名为k的数
{
int now=root;
while(now)
{
if(t[now].ok&&t[t[now].lson].valid+1==k) return t[now].val;//找到啦
if(t[t[now].lson].valid>=k) now=t[now].lson;//左边
else
{
k-=t[t[now].lson].valid+t[now].ok;//往右边走要减去排名
now=t[now].rson;//走啊
}
}
return -1;
}
void insert(int &k,int x)//插入
{
if(!k)//没有根则新建
{
k=nc[lnc--];t[k].val=x;
t[k].ok=t[k].total=t[k].valid=1;
t[k].lson=t[k].rson=0;
return;
}
t[k].total++;t[k].valid++;
if(t[k].val>=x) insert(t[k].lson,x);
else insert(t[k].rson,x);
if(isbad(k)) rebuild(k);//不平衡则重构
}
void delet_pos(int &k,int x)//删除排名为x的数
{
if(t[k].ok&&t[t[k].lson].valid+1==x) {t[k].ok=0;t[k].valid--;return;}
t[k].valid--;
if(t[t[k].lson].valid+t[k].ok>=x) delet_pos(t[k].lson,x);
else delet_pos(t[k].rson,x-(t[t[k].lson].valid+t[k].ok));
return;
}
void delet_val(int x)//删除这个数
{
delet_pos(root,find_rank(x));
if((double)t[root].total*0.8>t[root].valid) rebuild(root);
return;
}
signed main()
{
for(register int i=2000000;i>0;i--) nc[++lnc]=i;
m=read();
while(m--)
{
opt=read();x=read();
if(opt==1) insert(root,x);
if(opt==2) delet_val(x);
if(opt==3) write(find_rank(x)),putchar(10);
if(opt==4) write(find_kth(x)),putchar(10);
if(opt==5) write(find_kth(find_rank(x)-1)),putchar(10);
if(opt==6) write(find_kth(find_rank(x+1))),putchar(10);
}
}