• [HDU1890] Robotic Sort(Splay)


    前言

    适合入门但其实不算很裸的平衡树题

    题目

    洛谷

    HDU

    讲解

    在做这道题之前,最好先康康这道更板的题:

    P3391 【模板】文艺平衡树

    对于这道题,模拟就完事了

    我使用平衡树是(Splay)

    这道题的难点就在如何快速找到排名第(i)个数的位置

    至于(reverse)操作,在板题中应该已经熟悉了

    其实很简单,只需要将每个数与其对应在(Splay)上的点的编号记录下来,当你需要找到它的位置的时候,将它(splay)到根即可,它的位置就是左儿子大小+1

    注意我们插入的(1)(n+2)两个哨兵对各种造成的影响

    同时注意输出格式,末尾不能有多余空格

    代码

    int ID[MAXN];
    struct number
    {
    	int x,pos;
    }num[MAXN];
    
    bool cmp1(number a,number b)
    {
    	if(a.x != b.x) return a.x < b.x;
    	return a.pos < b.pos;
    }
    bool cmp2(number a,number b)
    {
    	return a.pos < b.pos;
    }
    
    #define lc t[x].ch[0]
    #define rc t[x].ch[1]
    struct Splay
    {
    	int tot,rt;//点,根
    	
    	struct node
    	{
    		int ch[2],val,f,siz,cnt;//儿子,value,父亲,size,count
    		bool fz;//翻转标记 
    	}t[MAXN];
    	
    	int newnode(int fa,int val)
    	{
    		++tot;
    		t[tot].ch[0] = t[tot].ch[1] = 0;
    		t[tot].siz = t[tot].cnt = 1;
    		t[tot].val = val;
    		t[tot].f = fa;
    		t[tot].fz = 0;
    		return tot;
    	}
    	bool chk(int x)//判断是左儿子还是右儿子 
    	{
    		return t[t[x].f].ch[1] == x;
    	}
    	void up(int x)
    	{
    		t[x].siz = t[lc].siz + t[rc].siz + t[x].cnt;
    	}
    	void down(int x)
    	{
    		if(!t[x].fz) return;
    		t[x].fz = 0;
    		t[lc].fz ^= 1;
    		t[rc].fz ^= 1;
    		swap(lc,rc);
    	}
    	int Build(int fa,int l,int r)
    	{
    		if(l > r) return 0;
    		int mid = (l+r) >> 1;
    		int x = newnode(fa,num[mid].x);
    		ID[num[mid].x] = x;//记录对应在平衡树上点的编号
    		lc = Build(x,l,mid-1);rc = Build(x,mid+1,r);
    		up(x);
    		return x;
    	}
    	void rotate(int x)
    	{
    		down(t[x].f);down(x);
    		int y = t[x].f,z = t[t[x].f].f;
    		bool cz = chk(y),cy = chk(x);
    		t[x].f = z; t[z].ch[cz] = x;
    		t[y].ch[cy] = t[x].ch[cy^1]; t[t[x].ch[cy^1]].f = y;
    		t[x].ch[cy^1] = y; t[y].f = x;
    		up(y);up(x);
    	}
    	void splay(int x,int to = 0)
    	{
    		while(t[x].f != to)
    		{
    			int y = t[x].f,z = t[t[x].f].f;
    			if(z != to)//双旋 
    			{
    				if(chk(x) == chk(y)) rotate(y);
    				else rotate(x);
    			}
    			rotate(x);
    		}
    		if(!to) rt = x;//记得改根 
    	}
    	int kth(int k)
    	{
    		int x = rt;
    		while(1)
    		{
    			down(x);
    			if(t[lc].siz >= k) x = lc;
    			else if(t[lc].siz + t[x].cnt < k) k -= t[lc].siz + t[x].cnt,x = rc;
    			else return x;
    		}
    	}
    	void reverse(int l,int r)
    	{
    		if(l == r) return;
    		l = kth(l-1);r = kth(r+1);
    		splay(l);splay(r,l);
    		t[t[r].ch[0]].fz ^= 1;
    	}
    	void print(int x)
    	{
    		if(!x) return;
    		down(x);
    		print(lc);
    		Put(t[x].val,'
    ');
    		print(rc);
    	}
    }S;
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);	
    	while(~scanf("%d",&n) && n)
    	{
    		S.tot = 0;
    		for(int i = 2;i <= n+1;++ i)
    			num[i].x = Read(),num[i].pos = i;
    		sort(num+2,num+n+2,cmp1);
    		num[1].pos = 1;num[n+2].pos = n+2;
    		for(int i = 1;i <= n+2;++ i)
    			num[i].x = i;
    		sort(num+1,num+n+3,cmp2);
    		S.rt = S.Build(0,1,n+2);
    		for(int i = 2;i <= n+1;++ i)
    		{
    			S.splay(ID[i]);
    			int pos = S.t[S.t[S.rt].ch[0]].siz;
    			Put(pos);
    			if(i == n+1) putchar('
    ');
    			else putchar(' ');
    			S.reverse(i,pos+1);
    		} 
    	}
    	return 0;
    }
    
  • 相关阅读:
    Python split分割字符串
    test markdown
    Python 数字格式转换
    Python 字符串改变
    Python axis的含义
    python 第三方库
    Spark快速入门
    vim快捷键
    Hadoop HDFS负载均衡
    YARN DistributedShell源码分析与修改
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/13649701.html
Copyright © 2020-2023  润新知