平衡树(模板)(Splay)
原题:洛谷P3369 普通平衡树
小的注意点:grank函数(比x小的数的个数+1)中,对答案的计算要在splay之前。
#include<bits/stdc++.h>
#define R register int
#define ll long long
#define I inline
using namespace std;
const int N=1e5+3;
int rt,tt,tot;
struct node
{
int val,cnt,sz;
int son[2],fa;
};
node t[N];
I void update(int x){t[x].sz=t[x].cnt+t[t[x].son[0]].sz+t[t[x].son[1]].sz;}
I bool getw(int x){return t[t[x].fa].son[1]==x;}
I void rotate(int x)
{
R y=t[x].fa,z=t[y].fa;
bool w=getw(x);
if(z)t[z].son[getw(y)]=x;
t[x].fa=z;
R &s=t[x].son[!w];
t[s].fa=y;t[y].son[w]=s;
t[y].fa=x;s=y;
update(y);
}
void splay(int x,int to)
{
if(!x)return;
for(R y;(y=t[x].fa)!=to;rotate(x))
if(t[y].fa!=to)rotate(getw(x)==getw(y)?y:x);
if(!to)rt=x;
update(x);
}
int find(int v)
{
R p;
for(p=rt;p&&t[p].val!=v;p=t[p].son[t[p].val<v]);
return splay(p,0),p;
}
void insert(int v)
{
++tot;
if(!rt)
{
rt=++tt;
t[rt].cnt=t[rt].sz=1;
t[rt].val=v;
return;
}
R p=rt,q; bool o;
while(p)
{
if(t[p].val==v)
{
splay(p,0);
++t[p].cnt;++t[p].sz;
return;
}
q=p; p=t[p].son[o=t[p].val<v];
}
t[q].son[o]=++tt;
t[tt].val=v;
t[tt].fa=q;
splay(tt,0);
++t[tt].cnt;++t[tt].sz;
}
void erase(int v)
{
R p=find(v);
if(!p)return;
if(t[p].cnt>1)
{
--t[p].cnt;
--t[p].sz;
return;
}
--tot;
R q=t[p].son[0];
if(!q)
{
t[rt=t[p].son[1]].fa=0;
return;
}
while(t[q].son[1])q=t[q].son[1];
splay(q,p);
t[q].son[1]=t[p].son[1];
rt=t[t[p].son[1]].fa=q;
t[q].fa=0;
update(q);
}
int grank(int v)
{
R ans=0,p=rt;
bool o;
while(p)
{
if(v==t[p].val)
{
int res=ans+t[t[p].son[0]].sz+1;
splay(p,0);//***
return res;
}
o=t[p].val<v;
if(o)ans+=t[t[p].son[0]].sz+t[p].cnt;
p=t[p].son[o];
}
return ans+1;
}
int arank(int k)
{
if(k>tot)return 0;
R p=rt;
while(1)
{
const R c0=t[t[p].son[0]].sz,c1=t[p].cnt+c0;
if(k>c0&&k<=c1)break;
if(k<=c0)p=t[p].son[0];
else p=t[p].son[1],k-=c1;
}
return splay(p,0),p;
}
int lower(int v)
{
R p=rt,id=0;
while(p)
{
if(t[p].val>=v)p=t[p].son[0];
else id=p,p=t[p].son[1];
}
return splay(id,0),id;
}
int upper(int v)
{
R p=rt,id=0;
while(p)
{
if(t[p].val<=v)p=t[p].son[1];
else id=p,p=t[p].son[0];
}
return splay(id,0),id;
}
int main()
{
int n;
scanf("%d",&n);
for(R i=1;i<=n;i++)
{
int op,x;
scanf("%d%d",&op,&x);
if(op==1)insert(x);
else if(op==2)erase(x);
else if(op==3)printf("%d\n",grank(x));
else if(op==4)printf("%d\n",t[arank(x)].val);
else if(op==5)printf("%d\n",t[lower(x)].val);
else printf("%d\n",t[upper(x)].val);
}
return 0;
}
原题:洛谷P3391 文艺平衡树
注意点:与上面类似,在访问子节点信息时记得先下传标记
#include<bits/stdc++.h>
#define R register int
#define ll long long
#define I inline
using namespace std;
const int N=1e5+3;
int rt=1,tt,a[N];
struct node
{
int val,sz;
int son[2],fa;
bool rev;
};
node t[N];
I void update(int x){t[x].sz=1+t[t[x].son[0]].sz+t[t[x].son[1]].sz;}
I bool getw(int x){return t[t[x].fa].son[1]==x;}
I void rotate(int x)
{
R y=t[x].fa,z=t[y].fa;
bool w=getw(x);
if(z)t[z].son[getw(y)]=x;
t[x].fa=z;
R &s=t[x].son[!w];
t[s].fa=y;t[y].son[w]=s;
t[y].fa=x;s=y;
update(y);
}
void splay(int x,int to)
{
if(!x)return;
for(R y;(y=t[x].fa)!=to;rotate(x))
if(t[y].fa!=to)rotate(getw(x)==getw(y)?y:x);
if(to==0)rt=x;
update(x);
}
I void pushdown(int p)
{
swap(t[p].son[0],t[p].son[1]);
t[t[p].son[0]].rev^=1;t[t[p].son[1]].rev^=1;
t[p].rev=0;
}
int build(int fa,int l,int r)
{
if(l>r)return 0;
int mid=l+r>>1,p=++tt;
t[p].val=mid;
t[p].fa=fa;
t[p].son[0]=build(p,l,mid-1);
t[p].son[1]=build(p,mid+1,r);
update(p);
return p;
}
int arank(int k)
{
R p=rt;
while(p)
{
if(t[p].rev)pushdown(p);//***
const R c=t[t[p].son[0]].sz+1;
if(k==c)break;
if(k<c)p=t[p].son[0];
else p=t[p].son[1],k-=c;
}
return p;
}
void reverse(int l,int r)
{
int x=arank(l),y=arank(r+2);
splay(y,0);splay(x,y);
t[t[x].son[1]].rev^=1;
}
int o;
void dfs(int p)
{
if(!p)return;
if(t[p].rev)pushdown(p);
dfs(t[p].son[0]);
a[o++]=t[p].val;
dfs(t[p].son[1]);
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
build(0,0,n+1);
for(R i=1;i<=m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
reverse(l,r);
}
dfs(rt);
for(R i=1;i<=n;i++)printf("%d ",a[i]);
return 0;
}
浙公网安备 33010602011771号