题目
思路
FHQTreap不能处理既要权值分裂,又要排名分裂的情况,所以我们按排名分裂,先预处理出排名,接下来权值就不重要了
code:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#include<iostream>
#include<cstdlib>
using namespace std;
inline int read()
{
int ret,c,f=1;
while (((c=getchar())> '9'||c< '0')&&c!='-');
if (c=='-') f=-1,ret=0;
else ret=c-'0';
while ((c=getchar())>='0'&&c<='9') ret=ret*10+c-'0';
return ret*f;
}
struct f{
int val,key,l,r,siz,lazy,mn;//真值,权值,左右儿子,子树大小,特殊标记这里指翻转
} tree[100006];
int cnt,n,m,root,l,r,z;
int New(int x)//建新点,传真值
{
tree[++cnt].val=x;
tree[cnt].mn=x;
tree[cnt].siz=1;
tree[cnt].key=rand();
return cnt;
}
void down(int id)//标记下传
{
if (!tree[id].lazy) return;
swap(tree[id].l,tree[id].r);
if (tree[id].l) tree[tree[id].l].lazy^=1;
if (tree[id].r) tree[tree[id].r].lazy^=1;
tree[id].lazy=0;
return;
}
void up(int id)//上传
{
tree[id].siz=tree[tree[id].l].siz+tree[tree[id].r].siz+1;
tree[id].mn=tree[id].val;
if (tree[id].l) tree[id].mn=min(tree[id].mn,tree[tree[id].l].mn);
if (tree[id].r) tree[id].mn=min(tree[id].mn,tree[tree[id].r].mn);
return;
}
void split(int id,int siz,int &l,int &r)//分裂,把从1开始长度为siz的部分拆出来
{
if (id==0)
{
l=r=0;
return;
}
down(id);
if (siz>tree[tree[id].l].siz)//递归左儿子
{
l=id;
split(tree[l].r,siz-1-tree[tree[l].l].siz,tree[l].r,r);
}
else//递归右儿子
{
r=id;
split(tree[r].l,siz,l,tree[r].l);
}
up(id);
return;
}
int merge(int l,int r)//合并,传入根节点编号
{
if (l==0||r==0)
{
return l+r;
}
if (tree[l].key<tree[r].key)//维护小根堆性质
{
down(l);
tree[l].r=merge(tree[l].r,r);
up(l);
return l;
}
else
{
down(r);
tree[r].l=merge(l,tree[r].l);
up(r);
return r;
}
}
int GR(int id)
{
int rak=1;
while (1)
{
down(id);
if (tree[id].l&&tree[tree[id].l].mn==tree[id].mn) id=tree[id].l;
else
{
if (tree[id].r&&tree[tree[id].r].mn==tree[id].mn) rak+=tree[tree[id].l].siz+1,id=tree[id].r;
else return rak+tree[tree[id].l].siz;
}
}
}
int v[100006];
struct fP{
int x,y;
} u[100006];
bool cmp(fP a,fP b)
{
if (a.x==b.x) return a.y<b.y;
return a.x<b.x;
}
int main()
{
n=read();
for (int i=1;i<=n;i++)
{
u[i].x=read();
u[i].y=i;
}
sort(u+1,u+1+n,cmp);
for (int i=1;i<=n;i++) v[u[i].y]=i;
for (int i=1;i<=n;i++)
{
root=merge(root,New(v[i]));
}
for (int i=1;i<=n;i++)
{
int x=GR(root);
split(root,x,l,r);
printf("%d ",x+i-1);
split(l,x-1,l,z);
tree[l].lazy^=1;
root=merge(l,r);
}
return 0;
}