传送门1
传送门2
传送门3
写在前面:woc……woc……大家知道为什么这么久没写题解了吧
思路:不会用指针千万别用!千万别手贱多写函数!千万多调用splay!
感谢http://blog.csdn.net/leolin_/article/details/6436037
http://codevs.cn/wiki/solution/?problem_id=4543
solution16851
注意:数组版splay,个人不喜欢压行,代码写了4k,个人感觉思路还是蛮清晰的,没有特别的技巧,不推荐作为模板使用
代码:
#include"bits/stdc++.h"
using namespace std;
int n,root,tot;
struct os
{
int left,right,father,sz,occ,data;
}a[300000];
void ct(int root)
{
a[root].sz=a[root].occ+a[a[root].left].sz+a[a[root].right].sz;
}
void made(int x)
{
a[++tot].data=x;
a[tot].sz=a[tot].occ=1;
}
void rotate(int x,bool flag)
{
int y=a[x].father;
if (flag)
{
a[y].left=a[x].right;
if (a[x].right) a[a[x].right].father=y;
a[x].father=a[y].father;
if (a[y].father)
{
if (a[a[y].father].left==y)
a[a[y].father].left=x;
else a[a[y].father].right=x;
}
a[x].right=y;
a[y].father=x;
}
else
{
a[y].right=a[x].left;
if (a[x].left) a[a[x].left].father=y;
a[x].father=a[y].father;
if (a[y].father)
{
if (a[a[y].father].left==y)
a[a[y].father].left=x;
else a[a[y].father].right=x;
}
a[x].left=y;
a[y].father=x;
}
ct(y);
ct(x);
}
void splay(int x,int goal)
{
int y;
while (a[x].father!=goal)
{
y=a[x].father;
if (a[y].father==goal)
{
if (a[y].left==x) rotate(x,1);
else rotate(x,0);
}
else if (a[a[y].father].left==y)
{
if (a[y].left==x) rotate(y,1);
else rotate(x,0);
rotate(x,1);
}
else
{
if (a[y].right==x) rotate(y,0);
else rotate(x,1);
rotate(x,0);
}
}
if (!goal) root=x;
}
void insert(int now,int x)
{
if (!root) {made(x);root=tot;return;}
int flag=0;
while (!flag)
{
a[now].sz++;
if (a[now].data==x) a[now].occ++,flag=2;
else if (a[now].data>x)
{
if (!a[now].left) made(x),a[now].left=tot,a[tot].father=now,flag=1;
else now=a[now].left;
}
else
{
if (!a[now].right) made(x),a[now].right=tot,a[tot].father=now,flag=1;
else now=a[now].right;
}
}
splay((flag==1)?tot:now,0);
}
int find(int now,int x)
{
while (now)
{
if (a[now].data==x) {splay(now,0);return now;}
else if (a[now].data>x) now=a[now].left;
else now=a[now].right;
}
return 0;
}
int find_max(int now)
{
int pa=a[now].father;
if (!now) return 0;
while (a[now].right) now=a[now].right;
splay(now,pa);
return now;
}
int find_min(int now)
{
int pa=a[now].father;
if (!now) return 0;
while (a[now].left) now=a[now].left;
splay(now,pa);
return now;
}
int find_next_min(int x)
{
int ans=0,now=root;
while (now)
{
if (a[now].data>=x) now=a[now].left;
else ans=(a[now].data>a[ans].data||!ans)?now:ans,now=a[now].right;
}
splay(ans,0);
return ans;
}
int find_next_max(int x)
{
int ans=0,now=root;
while (now)
{
if (a[now].data<=x) now=a[now].right;
else ans=(a[now].data<a[ans].data||!ans)?now:ans,now=a[now].left;
}
splay(ans,0);
return ans;
}
bool del(int x)
{
int now=find(root,x);
if (!now) return 0;
splay(now,0);
if (a[now].occ>1)
{
--a[now].occ;
--a[now].sz;
return 1;
}
if (!a[now].left&&!a[now].right) root=0;
else if (!a[now].left)
{
root=a[now].right;
a[a[now].right].father=0;
}
else if (!a[now].right)
{
root=a[now].left;
a[a[now].left].father=0;
}
else
{
splay(find_max(a[now].left),root);
a[a[now].left].right=a[now].right;
a[a[now].right].father=a[now].left;
a[a[now].left].father=0;
root=a[now].left;
ct(a[now].left);
}
ct(now);
return 1;
}
int Kth(int k)
{
int now=root;
int p;
while (now)
{
p=a[a[now].left].sz;
if (k>p&&k<=p+a[now].occ) break;
if (k<=p) now=a[now].left;
else k-=(p+a[now].occ),now=a[now].right;
}
splay(now,0);
return now;
}
int find_rank(int x)
{
int ans=0,now=root;
while (1)
{
if (x<a[now].data) now=a[now].left;
else
{
if (x==a[now].data)
{
ans+=a[a[now].left].sz+1;
break;
}
else ans+=a[a[now].left].sz+a[now].occ,now=a[now].right;
}
}
splay(now,0);
return ans;
}
main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
if (x==1) insert(root,y);
else if (x==2) del(y);
else if (x==3) printf("%d\n",find_rank(y));
else if (x==4) printf("%d\n",a[Kth(y)].data);
else if (x==5) printf("%d\n",a[find_next_min(y)].data);
else if (x==6) printf("%d\n",a[find_next_max(y)].data);
}
}
UPD
2017.3.23
学习后缀平衡树时搞了一发treap
#include<cstdio>
#include<iostream>
#include<cstdlib>
#define ls(x) tr[x].ch[0]
#define rs(x) tr[x].ch[1]
#define son(x,y) tr[x].ch[y]
#define M 100005
using namespace std;
int n,m,seed,root,cnt;
int in()
{
int t=0;char ch=getchar();bool f=0;
while (ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
while (ch>='0'&&ch<='9') t=(t<<1)+(t<<3)+ch-48,ch=getchar();
return f?-t:t;
}
int ran()
{
seed=seed^rand();
seed^=(seed<<7);
seed^=(seed>>3);
return seed;
}
struct Treap{
int key,fix,siz,occ,fa,ch[2];
void build(int Fa,int val)
{
key=val;
fa=Fa;
fix=ran();
siz=occ=1;
ch[0]=ch[1]=0;
}
}tr[M];
void count(int rt)
{
tr[rt].siz=tr[ls(rt)].siz+tr[rs(rt)].siz+tr[rt].occ;
}
void rotate(int x,bool f)
{
int y=tr[x].fa;
son(y,!f)=son(x,f);
if (son(x,f)) tr[son(x,f)].fa=y;
tr[x].fa=tr[y].fa;
if (tr[y].fa)
if (ls(tr[y].fa)==y) ls(tr[y].fa)=x;
else rs(tr[y].fa)=x;
son(x,f)=y;
tr[y].fa=x;
count(y);
count(x);
}
void insert(int rt,int val)
{
if (tr[rt].key==val) ++tr[rt].occ,++tr[rt].siz;
else if (tr[rt].key>val)
{
if (ls(rt))
insert(ls(rt),val);
else
tr[ls(rt)=++cnt].build(rt,val);
if (tr[ls(rt)].fix<tr[rt].fix)
{
if (!tr[rt].fa) root=ls(rt);
rotate(ls(rt),1);
}
}
else
{
if (rs(rt))
insert(rs(rt),val);
else
tr[rs(rt)=++cnt].build(rt,val);
if (tr[rs(rt)].fix<tr[rt].fix)
{
if (!tr[rt].fa) root=rs(rt);
rotate(rs(rt),0);
}
}
count(rt);
}
void del(int rt,int val)
{
if (tr[rt].key==val)
{
if (tr[rt].occ>1) --tr[rt].occ,--tr[rt].siz;
else if (!ls(rt)&&!rs(rt))
if (!tr[rt].fa) root=0;
else
{
if (rt==ls(tr[rt].fa)) ls(tr[rt].fa)=0;
else rs(tr[rt].fa)=0;
}
else if (!ls(rt))
if (!tr[rt].fa) root=rs(rt),tr[rs(rt)].fa=0;
else
{
tr[rs(rt)].fa=tr[rt].fa;
if (ls(tr[rt].fa)==rt) ls(tr[rt].fa)=rs(rt);
else rs(tr[rt].fa)=rs(rt);
}
else if (!rs(rt))
if (!tr[rt].fa) root=ls(rt),tr[ls(rt)].fa=0;
else
{
tr[ls(rt)].fa=tr[rt].fa;
if (ls(tr[rt].fa)==rt) ls(tr[rt].fa)=ls(rt);
else rs(tr[rt].fa)=ls(rt);
}
else
{
bool f=(tr[ls(rt)].fix<tr[rs(rt)].fix);
int y=son(rt,!f);
if (!tr[rt].fa) root=y;
rotate(y,f);
del(rt,val);
count(y);
}
}
else
{
if (tr[rt].key<val) del(rs(rt),val);
else del(ls(rt),val);
count(rt);
}
}
int Rank(int val)
{
int x=root,ans=0;
for (;;)
if (tr[x].key==val) return ans+tr[ls(x)].siz+1;
else if (tr[x].key<val) ans+=tr[ls(x)].siz+tr[x].occ,x=rs(x);
else x=ls(x);
}
int Kth(int k)
{
int x=root;
for (;;)
if (tr[ls(x)].siz<k&&k<=tr[ls(x)].siz+tr[x].occ) return tr[x].key;
else if (tr[ls(x)].siz>=k) x=ls(x);
else k-=tr[ls(x)].siz+tr[x].occ,x=rs(x);
}
int Pre(int val)
{
int x=root,ans=-1<<30;
for (;x;)
if (tr[x].key<val) ans=max(ans,tr[x].key),x=rs(x);
else x=ls(x);
return ans;
}
int Sub(int val)
{
int x=root,ans=1<<30;
for (;x;)
if (tr[x].key>val) ans=min(ans,tr[x].key),x=ls(x);
else x=rs(x);
return ans;
}
main()
{
srand(20170322);
int opt,x;
for (n=in();n;--n)
{
opt=in();x=in();
if (opt==1)
{
if (!root) tr[root=++cnt].build(0,x);
else insert(root,x);
}
else if (opt==2) del(root,x);
else if (opt==3) printf("%d\n",Rank(x));
else if (opt==4) printf("%d\n",Kth(x));
else if (opt==5) printf("%d\n",Pre(x));
else if (opt==6) printf("%d\n",Sub(x));
}
}