• 平衡树 Number


     

    问题 B: Number

    时间限制: 1 Sec  内存限制: 256 MB

    题目描述

    一个排列,求出了 a 数组,其中 ai 表示第 i 个数左边有多少个数比它小

    计算出原来的排列

    输入

    第一行输入 n 接下来 n - 1 个整数 ai,下标从 2 开始

    输出

    输出 n 个整数表示原排列

    样例输入

    51210

    样例输出

    24531

    提示


    对于 20% 的数据满足:1 ≤ n ≤ 10



    对于 50% 的数据满足:1 ≤ n ≤ 1000



    对于 100% 的数据满足,1 ≤ n ≤ 100000



    保证解存在

         做法有很多:一,二分加树状数组;

                               二,链表(TLE一半N^2效率)

                               三,平衡树。

        最后一个点能得到它在整个数组中的排名,得知自己的号,扣掉了一个数,因此第n-1个点也知道了,

        那么如何优化找排名的过程——平衡树。

        先推进去1~n,在一个一个删。

        

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<set>
    using namespace std;
    int read()
    {
    	int sum=0,f=1;char x=getchar();
    	while(x<'0'||x>'9'){if(x=='-')f=-1;x=getchar();}
    	while(x>='0'&&x<='9'){sum=sum*10+x-'0';x=getchar();}
    	return sum*f;
    }
    int n,a[1000005],b[1000005],root,hh;
    struct tree
    {
        int l,r,size,tot,h,rd;
    } t[100005];
    void l_swap(int &root)
    {
        int k=t[root].r;
        t[root].r=t[k].l;
        t[k].l=root;
        t[k].size=t[root].size;
        t[root].size=t[t[root].l].size+t[t[root].r].size+t[root].tot;
        root=k;
    }
    void r_swap(int &root)
    {
        int k=t[root].l;
        t[root].l=t[k].r;
        t[k].r=root;
        t[k].size=t[root].size;
        t[root].size=t[t[root].l].size+t[t[root].r].size+t[root].tot;
        root=k;
    }
    void build(int &root,int k)
    {
        if(!root)
        {
            root=++hh;
            t[root].h=k;
            t[root].size=t[root].tot=1;
            t[root].rd=rand();
            return;
        }
        t[root].size++;
        if(t[root].h==k)t[root].tot++;
        else
        {
            if(t[root].h>k)
            {
                build(t[root].l,k);
                if(t[t[root].l].rd<t[root].rd);
                   r_swap(root);
            }
            else
            {
                build(t[root].r,k);
                if(t[t[root].r].rd<t[root].rd)
                    l_swap(root);
            }
        }
    }
    void del(int &root,int k)
    {
        if(!root)return;
        if(t[root].h==k)
        {
            if(t[root].tot>1)
            {
                t[root].tot--;
                t[root].size--;
                return;
            }
            if(t[root].l*t[root].r==0)
                root=t[root].l+t[root].r;
            else
            {
                if(t[t[root].l].rd<t[t[root].r].rd)
                    r_swap(root);
                else
                    l_swap(root);
                del(root,k);
            }
        }
        else
        {
             t[root].size--;
             if(k>t[root].h)del(t[root].r,k);
             else del(t[root].l,k);
        }
    }
    int Q(int &root,int k)
    {
        if(!root)return 0;
        if(t[t[root].l].size+1<=k&&t[t[root].l].size+t[root].tot>=k)
             return t[root].h;
        if(t[t[root].l].size>=k)
             return Q(t[root].l,k);
        if(t[t[root].l].size<k)
             return Q(t[root].r,k-t[root].tot-t[t[root].l].size);
    }
    int main()
    {
    	//freopen("number.in","r",stdin);
    //	freopen("number.out","w",stdout);
    	n=read();
    	build(root,1);
    	for(int i=2;i<=n;i++)
    	{
    	    a[i]=read();
    	    build(root,i);
    	}
    	for(int i=n;i>=1;i--)
    	{
    	    int k=Q(root,a[i]+1);
    	    b[i]=k;
    		del(root,k);
    	}	
    	for(int i=1;i<=n;i++)printf("%d
    ",b[i]);
    }

  • 相关阅读:
    使用C# 实现串口拨号器的SIM卡通信
    物联网协议Coap协议介绍
    C#实现简单的串口通信
    C#硬件访问(摄像头、麦克风)
    请问在电脑里PNP是什么意思啊?
    原码,反码,补码,及Java中数字表示方法
    3_PHP表达式_5_数据类型转换_类型强制转换
    3_PHP表达式_4_PHP运算符
    3_PHP表达式_5_数据类型转换_类型自动转换
    3_PHP表达式_3_有关变量或常量状态的函数
  • 原文地址:https://www.cnblogs.com/QTY2001/p/7632731.html
Copyright © 2020-2023  润新知