hdu 5592 BestCoder Round #65 1003

来源:互联网 发布:淘宝的91论坛共享号 编辑:程序博客网 时间:2024/05/21 22:38

                                           ZYB's Premutation

                                          Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)


Problem Description
ZYB has a premutation P,but he only remeber the reverse log of each prefix of the premutation,now he ask you to
restore the premutation.

Pair (i,j)(i<j) is considered as a reverse log if Ai>Aj is matched.
 

Input
In the first line there is the number of testcases T.

For each teatcase:

In the first line there is one number N.

In the next line there are N numbers Ai,describe the number of the reverse logs of each prefix,

The input is correct.

1T5,1N50000
 

Output
For each testcase,print the ans.
 

Sample Input
130 1 2
 

Sample Output
3 1 2
 

Source
BestCoder Round #65
题目大意:ZYB有一个排列PPP,但他只记得PPP中每个前缀区间的逆序对数,现在他要求你还原这个排列.

(i,j)(i<j)被称为一对逆序对当且仅当Ai>AjA_i>A_jAi>Aj
解题思路:

首先既然给了[1, i-1][1, i]区间逆序对的个数,自然可以求出与i组成逆序对的个数,自然就是i前面比i大的个数,自然也就能求出i前面比i小的个数。

然后我考虑最后一个数,由于它在最后一个,所以所有数都在它前面,自然如果知道它前面有多少个比他小的,就知道它是几了。不妨设最后一个是p,然后考虑倒数第二个,如果它前面有x个比他小的,那么倒数第二个自然是除掉p以外排在x+1位置上的那个数。以此类推。

有了这个需要数据结构的支持,可以用树状数组维护[1, n]区间1的个数,然后一旦找到某个数,就让它置0。然后找当前位置前面有x个数比他小,即在树状数组中前缀和为x+1的那个区间右值

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5592

代码:
#include <iostream>#include <stdio.h>using namespace std;const int maxn=50010;struct Tree{    int l,r;    int val;}tree[maxn<<2];void pushup(int root){    tree[root].val=tree[root<<1].val+tree[root<<1|1].val;}void build(int root,int l,int r){    tree[root].l=l;    tree[root].r=r;    if(l==r)    {        tree[root].val=1;        return;    }    int mid=(tree[root].l+tree[root].r)>>1;    build(root<<1,l,mid);    build(root<<1|1,mid+1,r);    pushup(root);}int query(int root,int k){    if(tree[root].l==tree[root].r)    {        tree[root].val=0;        return tree[root].l;    }   // int mid=(tree[root].l+tree[root].r)>>1;    int ret;    if(tree[root<<1|1].val>=k)    ret = query(root<<1|1,k);    else    ret=query(root<<1,k-tree[root<<1|1].val);    pushup(root);    return ret;}int main(){    int t;    cin>>t;    int a[maxn];    int ans[maxn];    while(t--)    {        int n;        cin>>n;        for(int i=1;i<=n;i++)        scanf("%d",&a[i]);        a[0]=0;        build(1,1,n);        //cout<<tree[1].val<<endl;        for(int i=n;i>=1;i--)        {            int x=a[i]-a[i-1];            //cout<<x<<endl;            ans[i]=query(1,x+1);            //cout<<ans[i]<<endl;        }        for(int i=1;i<=n-1;i++)        cout<<ans[i]<<" ";        cout<<ans[n]<<endl;    }    return 0;}

 
 
0 0
原创粉丝点击