1552 & 3506. [CQOI2014]排序机械臂平衡树-splay

Posted Refun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1552 & 3506. [CQOI2014]排序机械臂平衡树-splay相关的知识,希望对你有一定的参考价值。

Description

技术分享图片

Input

输入共两行,第一行为一个整数N,N表示物品的个数,1<=N<=100000。
第二行为N个用空格隔开的正整数,表示N个物品最初排列的编号。

Output

输出共一行,N个用空格隔开的正整数P1,P2,P3…Pn,Pi表示第i次操作前第i小的物品所在的位置。 
注意:如果第i次操作前,第i小的物品己经在正确的位置Pi上,我们将区间[Pi,Pi]反转(单个物品)。

Sample Input

6
3 4 5 1 6 2

Sample Output

4 6 4 5 6 6
 
记录下每个装置对应位置然后依次splay翻转区间即可。
 
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define N (100000+100)
using namespace std;
struct node
{
	int id,num;
} b[N];
int Key[N],Rev[N],Size[N];
int Father[N],Son[N][2];
int n,Root,a[N],Rank[N];

bool cmp(node a,node b)
{
	return a.num==b.num?a.id<b.id:a.num<b.num;
}
inline int Get(int x)
{
    return Son[Father[x]][1]==x;
}

inline void Update(int x)
{
    Size[x]=Size[Son[x][0]]+Size[Son[x][1]]+1;
}

inline void Pushdown(int x)
{
    if (Rev[x])
    {
        Rev[x]=0;
        swap(Son[x][0],Son[x][1]);
        Rev[Son[x][0]]^=1;
        Rev[Son[x][1]]^=1;	
    }
}

inline void Rotate(int x)
{
    Pushdown(Father[x]);
    Pushdown(x);
    int wh=Get(x);
    int fa=Father[x],fafa=Father[fa];
    Son[fa][wh]=Son[x][wh^1];
    Father[fa]=x;
    if (Son[fa][wh]) Father[Son[fa][wh]]=fa;
    Son[x][wh^1]=fa;
    Father[x]=fafa;
    if (fafa) Son[fafa][Son[fafa][1]==fa]=x;
    Update(fa);
    Update(x);
}

inline void Splay(int x,int tar)
{
    for (int fa;(fa=Father[x])!=tar;Rotate(x))
        if (Father[fa]!=tar)
            Rotate(Get(fa)==Get(x)?fa:x);
    if (!tar) Root=x;
}

void Build(int l,int r,int fa)
{
    if (l>r) return;
    if (l==r)
    {
        Size[l]=1;
        Father[l]=fa;
        Son[fa][l>fa]=l;
        return;
    }
    int mid=(l+r)>>1;
    Build(l,mid-1,mid);
    Build(mid+1,r,mid);
    Father[mid]=fa;
    Son[fa][mid>fa]=mid;
    Update(mid);
}

int Findx(int x)
{
    int now=Root;
    while (1)
    {
        Pushdown(now);
        if (Size[Son[now][0]]>=x)
            now=Son[now][0];
        else
        {
            x-=Size[Son[now][0]];
            if (x==1)
            {
                Splay(now,0);
                return now;
            }
            x--;
            now=Son[now][1];
        }
    }
}

inline int Split(int x,int y)
{
    int xx=Findx(x),yy=Findx(y);
    Splay(xx,0);
    Splay(yy,xx);
    return Son[yy][0];
}

int main()
{
	scanf("%d",&n);
	for (int i=1; i<=n; ++i)
	{
		scanf("%d",&a[i+1]);
		b[i].id=i+1;
		b[i].num=a[i+1];
	}
	sort(b+1,b+n+1,cmp);
	for (int i=1; i<=n; ++i)
		Rank[i]=b[i].id;
	Build(1,n+2,0);
	Root=(n+3)/2;
	for (int i=1; i<=n; ++i)
	{
		Splay(Rank[i],0);
		int ans=Size[Son[Root][0]]+1;
		printf("%d ",ans-1);
		int hh=Split(i,ans+1);
		Rev[hh]^=1;
	}
}

 

以上是关于1552 & 3506. [CQOI2014]排序机械臂平衡树-splay的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ-1552&3506robotic sort&排序机械臂 Splay

bzoj1552/3506[Cerc2007]robotic sort splay翻转,区间最值

bzoj 3506[Cqoi2014]排序机械臂 - splay

Bzoj3506: [Cqoi2014]排序机械臂

BZOJ3505 & ??????P3166 [Cqoi2014]???????????? ?????????????????????

luogu P4170ybtoj 区间DP课堂过关 例题2木板涂色 & [CQOI2007]涂色