HDU1890

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define Keytree (ch[ ch[root][1] ][0])
const int maxn = 100010;
struct node {
    int num,id;
}in[maxn];
int id[maxn];
int cmp(node a,node b){
    if(a.num!=b.num) return a.num<b.num;
    return a.id<b.id;
}
struct SplayTree{
    int tot,root;
    int pre[maxn];
    int size[maxn];
    int ch[maxn][2];
    inline void Rotate(int x, int c) {    // 旋转, c=0 左旋, c=1 右旋
        int y = pre[x];
        pushdown(y);
        pushdown(x);
        ch[y][!c] = ch[x][c];
        if ( ch[x][c] )    pre[ ch[x][c] ] = y;
        pre[x] = pre[y];
        if ( pre[y] )    ch[ pre[y] ][ ch[pre[y]][1] == y ] = x;
        ch[x][c] = y;
        pre[y] = x;
        pushup(y);
    }
    inline void Splay(int x, int f) {    // 把结点x转到结点f的下面
        pushdown(x);
        while ( pre[x] != f ) {
            int y = pre[x], z = pre[y];
            pushdown(z);    pushdown(y);    pushdown(x);    // 旋转前必须先去除反转标记
            if ( pre[ pre[x] ] == f ) {
                Rotate(x, ch[pre[x]][0] == x);
            }
            else {
                if ( ch[z][0] == y ) {
                    if ( ch[y][0] == x ) 
                        Rotate(y, 1), Rotate(x, 1);
                    else 
                        Rotate(x, 0), Rotate(x, 1);
                }
                else {
                    if ( ch[y][0] == x ) 
                        Rotate(x, 1), Rotate(x, 0);
                    else 
                        Rotate(y, 0), Rotate(x, 0);
                }
            }
        }
        pushup(x);
        if ( f == 0 )    root = x;
    }
    inline void Select(int k, int f) {    // 把第k个点旋转到f的下面
        int x = root;
        while ( 1 ) {
            pushdown(x);
            if ( k == size[ ch[x][0] ] + 1 ) 
                break;
            if ( k <= size[ ch[x][0] ] )
                x = ch[x][0];
            else {
                k -= (size[ ch[x][0] ] + 1);
                x = ch[x][1];
            }
        } 
        Splay(x, f);
    }
    inline void del_root(){//删除根节点
        int t=root;
        if(ch[root][1]) {
            root=ch[root][1];
            Select(1,0);//把右子树中序遍历的第一个点旋转到根(因为这个点的左儿子肯定为空)
            ch[root][0]=ch[t][0];//将原先根节点的左子树接到当前根节点的左子树上
            if(ch[t][0]) pre[ch[t][0]]=root;
        }
        else 
            root=ch[root][0];

        pre[root]=0;
        pushup(root);
    }
    inline void pushup(int x){
        size[x]=size[ ch[x][0] ] + size[ ch[x][1] ] +1;
    }
    inline void pushdown(int x){
        if(flip[x]){
            flip[x]=0;
            flip[ch[x][0]]^=1;
            flip[ch[x][1]]^=1;
            swap(ch[x][0],ch[x][1]);
        }
    }
    void Newnode(int &x,int f){
        x=++tot;
        pre[x]=f;
        ch[x][0]=ch[x][1]=0;
        flip[x]=0;
        size[x]=1;
    }
    void build(int &x,int l,int r,int f){
        if(l>r) return ;
        int mid=(l+r)>>1;
        Newnode(x,f);
        map[id[mid]]=x;
        build(ch[x][0],l,mid-1,x);
        build(ch[x][1],mid+1,r,x);
        pushup(x);
    }
    void init(int n){
        int i;
        pre[0]=ch[0][0]=ch[0][1]=0;
        size[0]=flip[0]=tot=0;
        for(i=1;i<=n;i++) {
            scanf("%d",&in[i].num);
            in[i].id=i;
        }
        sort(in+1,in+n+1,cmp);
        for(i=1;i<=n;i++) id[in[i].id]=i;
        map[id[1]] = 1;
        map[id[n]] = 2;
        Newnode(root,0);
        Newnode(ch[root][1],root);
        build(Keytree,2,n-1,ch[root][1]);
        pushup(ch[root][1]);
        pushup(root);
    }
    void solve(int n){
        for(int i=1;i<=n;i++){
            Splay(map[i],0);
            printf("%d",i+size[ch[root][0]]);
            if(i<n) printf(" ");
            flip[ch[root][0]]^=1;
            del_root();
        }
        puts("");
    }
    int map[maxn];
    int flip[maxn];
}spt;
int main(){
    int n;
    while(scanf("%d",&n),n)    {
        if(n==1) {scanf("%*d");printf("1\n");continue;}
        spt.init(n);
        spt.solve(n);
    }
    return 0;
}


风格更新后:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define inf 0x3f3f3f3f
#define maxn 100010
#define LL long long int
#define Key_value ch[ch[root][1]][0]

struct node
{
	int num,id;
}in[maxn];

int id[maxn];
bool cmp(node a,node b)
{
	if(a.num != b.num)	return a.num < b.num;
	return a.id < b.id;
}

struct SplayTree
{
	int pre[maxn],ch[maxn][2],size[maxn],flip[maxn],map[maxn],root,cnt;
	
	void init(int n)
	{
		root = cnt = 0;
		pre[0] = ch[0][0] = ch[0][1] = 0;
		size[0] = flip[0] = 0;
		for(int i = 1;i <= n;i++)
		{
			scanf("%d",&in[i].num);
			in[i].id = i;
		}
		sort(in+1,in+n+1,cmp);
		for(int i = 1;i <= n;i++)	id[in[i].id] = i;
		map[id[1]] = 1;
		map[id[n]] = 2;
		NewNode(root,0);
		NewNode(ch[root][1],root);
		BuildTree(Key_value,2,n-1,ch[root][1]);
		PushUp(ch[root][1]);
		PushUp(root);
	}

	void BuildTree(int & x,int l,int r,int father)
	{
		if(l > r)	return;
		int mid = (l+r) >> 1;
		NewNode(x,father);
		map[id[mid]] = x;
		if(l < mid)
			BuildTree(ch[x][0],l,mid-1,x);
		if(r > mid)
			BuildTree(ch[x][1],mid+1,r,x);
		PushUp(x);
	}

	void NewNode(int & r,int father)
	{
		r = ++cnt;
		pre[r] = father;
		ch[r][0] = ch[r][1] = 0;
		size[r] = 1;
		flip[r] = 0;
	}

	void PushDown(int r)
	{
		if(flip[r])
		{
			flip[r] = 0;
			flip[ch[r][0]] ^= 1;
			flip[ch[r][1]] ^= 1;
			swap(ch[r][0],ch[r][1]);
		}
	}
	
	void PushUp(int r)
	{
		size[r] = size[ch[r][0]] + size[ch[r][1]] + 1;
	}

	void Rotate(int x,int kind)
	{
		int y = pre[x];
		PushDown(y);
		PushDown(x);
		ch[y][!kind] = ch[x][kind];
		pre[ch[x][kind]] = y;
		if(pre[y])
			ch[pre[y]][ch[pre[y]][1]==y] = x;
		pre[x] = pre[y];
		ch[x][kind] = y;
		pre[y] = x;
		PushUp(y);
	}

	void Splay(int r,int goal)
	{
		PushDown(r);
		while(pre[r] != goal)
		{
			int y = pre[r],z = pre[y];
			PushDown(z);	PushDown(y);	PushDown(r);
			if(pre[pre[r]] == goal)
			{
				Rotate(r,ch[pre[r]][0] == r);
			}
			else
			{
				int kind = ch[pre[y]][0] == y;
				if(ch[y][kind] == r)
				{
					Rotate(r,!kind);
					Rotate(r,kind);
				}
				else
				{
					Rotate(y,kind);
					Rotate(r,kind);
				}
			}
		}
		PushUp(r);
		if(goal == 0)	root = r;
	}

	void RotateTo(int k,int goal)
	{
		int r = root;
		while(1)
		{
			PushDown(r);
			if(k == size[ch[r][0]] + 1)
				break;
			if(k <= size[ch[r][0]])
				r = ch[r][0];
			else
			{
				k -= size[ch[r][0]] + 1;
				r = ch[r][1];
			}
		}
		Splay(r,goal);
	}

	void del_root()
	{
		int t = root;
		if(ch[root][1])
		{
			root =  ch[root][1];
			RotateTo(1,0);
			ch[root][0] = ch[t][0];
			if(ch[t][0])	pre[ch[t][0]] = root;
		}
		else root = ch[root][0];
		pre[root] = 0;
		PushUp(root);
	}

	void solve(int n)
	{
		init(n);
		for(int i = 1;i <= n;i++)
		{
			Splay(map[i],0);
			printf("%d",i+size[ch[root][0]]);
			if(i < n)	printf(" ");
			flip[ch[root][0]] ^= 1;
			del_root();
		}
		puts("");
	}
}spt;

int main()
{
	int n;
	while(scanf("%d",&n)!=EOF && n)
	{
		if(n == 1)
		{
			scanf("%*d");
			printf("1\n");
			continue;
		}
		spt.solve(n);
	}
	return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define maxn 100080
#define Key_value ch[ch[root][1]][0]
int Rank[maxn],Map[maxn];

struct Item
{
	int key,id;
	bool operator < (const Item & a) const
	{
		if(key != a.key)return key < a.key;
		return id < a.id;
	}
}item[maxn];

struct SpalyTree
{
	int pre[maxn],ch[maxn][2],size[maxn],flip[maxn];
	int root,cnt;

	void init(int n)
	{
		cnt = root = 0;
		ch[0][0] = ch[0][1] = size[0] = pre[0] = flip[0] = 0;
		NewNode(root,1,0);
		NewNode(ch[root][1],n,root);
		Buildtree(Key_value,2,n-1,ch[root][1]);
		PushUp(ch[root][1]);
		PushUp(root);
	}

	void NewNode(int & r,int k,int father)
	{
		r = ++cnt;
		ch[r][0] = ch[r][1] = flip[r] = 0;
		pre[r] = father;
		size[r] = 1;
		Map[Rank[k]] = r;
	}

	void PushDown(int x)
	{
		if(flip[x])
		{
			flip[x] = 0;
			flip[ch[x][0]] ^= 1;
			flip[ch[x][1]] ^= 1;
			swap(ch[x][0],ch[x][1]);
		}
	}

	void PushUp(int x)
	{
		int l = ch[x][0],r = ch[x][1];
		size[x] = size[l] + size[r] + 1;
	}

	void Buildtree(int & r,int L,int R,int father)
	{
		if(L > R)return;
		int mid = (L+R)>>1;
		NewNode(r,mid,father);
		Buildtree(ch[r][0],L,mid-1,r);
		Buildtree(ch[r][1],mid+1,R,r);
		PushUp(r);
	}

	void Rotate(int x,int kind)
	{
		int y = pre[x];
		PushDown(y);
		PushDown(x);
		ch[y][!kind] = ch[x][kind];
		pre[ch[x][kind]] = y;
		if(pre[y])
			ch[pre[y]][ch[pre[y]][1]==y] = x;
		pre[x] = pre[y];
		ch[x][kind] = y;
		pre[y] = x;
		PushUp(y);
	}

	void Splay(int r,int goal)
	{
		PushDown(r);//为什么去了这个会超时.假设pre[r] == goal。而且r有懒惰标记
		//如果这里没有PushDown。这里懒惰标记就直接给del_root函数搞没了。。
		while(pre[r] != goal)
		{
			int y = pre[r],z = pre[y];
			PushDown(z);	PushDown(y);	PushDown(r);//这里不加会超时,想想
			if(pre[pre[r]] == goal)
				Rotate(r,ch[pre[r]][0] == r);
			else 
			{
				int kind = (ch[pre[y]][0] == y);
				if(ch[y][kind] == r)
				{
					Rotate(r,!kind);
					Rotate(r,kind);
				}
				else 
				{
					Rotate(y,kind);
					Rotate(r,kind);
				}
			}
		}
		PushUp(r);
		if(goal == 0)	root = r;
	}
	
	int Get_Kth(int r,int k)
	{
		PushDown(r);
		int t = size[ch[r][0]] + 1;
		if(t == k)
			return r;
		if(t > k)
			return Get_Kth(ch[r][0],k);
		else return Get_Kth(ch[r][1],k-t);
	}

	void del_root()
	{
		int t = root;
		if(ch[root][1])
		{
			root = ch[root][1];
			int x = Get_Kth(root,1);
			Splay(x,0);
			ch[root][0] = ch[t][0];
			if(ch[t][0])	pre[ch[t][0]] = root;
		}
		else root = ch[root][0];
		pre[root] = 0;
		PushUp(root);
	}

	void solve(int n)
	{
		init(n);
		for(int i = 1;i <= n;i++)
		{
			Splay(Map[i],0);
			printf("%d",i+size[ch[root][0]]);
			flip[ch[root][0]] ^= 1;
			del_root();
			if(i == n)	printf("\n");
			else printf(" ");
		}
	}
}spt;

int main()
{
	//freopen("in.txt","r",stdin);
	int n;
	while(scanf("%d",&n)!=EOF && n)
	{
		if(n == 1)
		{
			scanf("%*d");
			printf("1\n");
			continue;
		}
		for(int i = 1;i <= n;i++)
		{
			scanf("%d",&item[i].key);
			item[i].id = i;
		}
		sort(item+1,item+1+n);
		for(int i = 1;i <= n;i++)
		{
			Rank[item[i].id] = i;
		}//Rank数组表示第几个进来的排第几。
		spt.solve(n);
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值