BestCoder Round #65 ZYB's Premutation

ZYB's Premutation

 
 Accepts: 218
 
 Submissions: 983
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 131072/131072 K (Java/Others)
问题描述
ZYBZYB有一个排列PP,但他只记得PP中每个前缀区间的逆序对数,现在他要求你还原这个排列.

(i,j)(i < j)(i,j)(i<j)被称为一对逆序对当且仅当A_i>A_jAi>Aj
输入描述
第一行一个整数TT表示数据组数。

接下来每组数据:

第一行一个正整数NN,描述排列的长度.

第二行NN个正整数A_iAi,描述前缀区间[1,i][1,i]的逆序对数.

数据保证合法.

1 \leq T \leq 51T5,1 \leq N \leq 500001N50000
输出描述
TT行每行NN个整数表示答案的排列.
输入样例
1
3
0 1 2
输出样例
3 1 2
解:线段树过。但是,我做对了也不晓得咋个做的,蒙对的吧
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxm=1e5+10;
int sum[maxm<<2];
int a[maxm];
int ans[maxm];
void build(int l,int r,int rt)
{
    sum[rt]=r-l+1;
    if(l==r)
    {
        return;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
}
int querty(int L,int R,int l,int r,int rt)
{
    sum[rt]--;
    if(l==r)
    {
        return l;
    }
    int m=(l+r)>>1;
    if(sum[rt<<1|1]>=L)
        return querty(L,R,rson);
    else
        return querty(L-sum[rt<<1|1],R,lson);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        for(int i=n;i>=1;i--)
        {
            a[i]-=a[i-1];
        }
        build(1,n,1);
        for(int i=n;i>=1;i--)
        {
            ans[i]=querty(a[i]+1,n,1,n,1);
        }
        for(int i=1;i<=n;i++)
        {
            if(i==n)
                printf("%d\n",ans[i]);
            else
                printf("%d ",ans[i]);
        }
    }
    return 0;
}

你可能感兴趣的:(BestCoder Round #65 ZYB's Premutation)