题目概述
BZOJ原题意:同OJ1552。BZOJ1552:权限题。城市套路深,我要回农村。
给出一个长度为
n
的序列,执行
ps:如果相同取位置靠前的。
解题报告
QAQ,查了两天,发现我没看到相同取靠前。于是我用基数排序将相同的硬是搞成了不相同的……
直接Splay,只不过要多实现一个得到排名的函数,需要记录 fa 。
示例程序
#include<cstdio>
#include<algorithm>
#define fr first
#define sc second
#define mp make_pair
using namespace std;
const int maxn=100000;
int n,a[maxn+5],b[maxn+5],ha[maxn+5];
struct node
{
node *son[2],*fa;int si,ID;pair<int,node*> MIN;bool flip;
node(node *p=0,node *f=0,int k=0,int s=1) {son[0]=son[1]=p;fa=f;ID=k;si=s;MIN=mp(ID,this);flip=false;}
inline int cmp(int &k) {if (k<=son[0]->si) return 0;if (k>son[0]->si+1) return k-=son[0]->si+1,1;return -1;}
inline void Pushup() {si=son[0]->si+1+son[1]->si;MIN=min(son[0]->MIN,son[1]->MIN);MIN=min(MIN,mp(ID,this));}
inline void Addflip() {swap(son[0],son[1]);flip^=1;}
inline void Pushdown() {if (!flip) return;flip=false;son[0]->Addflip();son[1]->Addflip();}
}nil(&nil,&nil,maxn+5,0);
typedef node* P_node;
node tem[maxn+5];P_node si=tem,null=&nil,ro;
#define newnode(fa,k) (*si=node(null,fa,k),si++)
P_node Build(int L,int R,P_node fa=null)
{
if (L>R) return null;int mid=L+(R-L>>1);P_node now=newnode(fa,a[mid]);
return now->son[0]=Build(L,mid-1,now),now->son[1]=Build(mid+1,R,now),now->Pushup(),now;
}
inline void Rotate(P_node &p,int d)
{
P_node t=p->son[d^1];p->son[d^1]=t->son[d];t->son[d]=p;
t->fa=p->fa;p->fa=t;if (p->son[d^1]!=null) p->son[d^1]->fa=p;
p->Pushup();t->Pushup();p=t;
}
void Splay(P_node &p,int k)
{
p->Pushdown();int d=p->cmp(k);
if (~d)
{
P_node &P=p->son[d];P->Pushdown();int D=P->cmp(k);
if (~D) {Splay(P->son[D],k);if (d==D) Rotate(p,d^1); else Rotate(P,D^1);}
Rotate(p,d^1);
}
}
inline void getLR(int L,int R) {R+=2;Splay(ro,L);ro->cmp(R);Splay(ro->son[1],R);}
#define NOW ro->son[1]->son[0]
inline void Flip(int L,int R) {getLR(L,R);NOW->Addflip();}
#define Son(p) ((p)==(p)->fa->son[1])
inline int getrk(P_node p,P_node ro) //得到排名
{
static int top=0,rk;static P_node stk[maxn+5];
for (P_node i=p;i!=ro;i=i->fa) stk[++top]=i;stk[++top]=ro;
while (top) stk[top--]->Pushdown();rk=p->son[0]->si+1;
for (;p!=ro;p=p->fa) if (Son(p)) rk+=p->fa->son[0]->si+1;return rk;
}
inline int Find(int x)
{
int L=1,R=b[0];
for (int mid=L+(R-L>>1);L<=R;mid=L+(R-L>>1))
if (b[mid]<=x) L=mid+1; else R=mid-1;
return R;
}
int main()
{
freopen("program.in","r",stdin);
freopen("program.out","w",stdout);
scanf("%d",&n);for (int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
sort(b+1,b+1+n);b[0]=unique(b+1,b+1+n)-(b+1);for (int i=1;i<=n;i++) ha[a[i]=Find(a[i])]++;
for (int i=1;i<=b[0];i++) ha[i]+=ha[i-1];for (int i=n;i>=1;i--) a[i]=ha[a[i]]--;ro=Build(0,n+1);
for (int i=1;i<=n;i++)
{
getLR(i,n);int rk=getrk(NOW->MIN.sc,NOW)+i-1;printf("%d",rk);
Flip(i,rk);putchar(i<n?' ':'\n');
}
return 0;
}