hdu 5529-ZYB's Premutation(逆推逆序数变形)

针对ZYB'sPermutation问题,介绍了一种通过已知逆序对数还原原始排列的方法,并给出了具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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
 
 
思路:
    这题与这题(点我)的对立,对立那题是左边有几个比自己小,而这题变成了,右边有几个比自己小。所以这题可以转化为对立的那题。所以只要在右边找到有几个比自己小的数,然后从大到小存,就行了。
 
 
AC代码:
 
 
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
#define lson (rt<<1)
#define rson (rt<<1|1)
#define T 50010
struct node
{
    int L,R,mid;
    int sum;
}tree[T<<2];
int v[T],ans[T],c;
void Pushup(int rt)
{
    tree[rt].sum = tree[lson].sum+tree[rson].sum;
}
void build(int rt,int L,int R)
{
    tree[rt].L = L,tree[rt].R = R;
    tree[rt].mid = (L+R)>>1;
    if(L==R){
        tree[rt].sum =1;
        return;
    }
    build(lson,L,tree[rt].mid);
    build(rson,tree[rt].mid+1,R);
    Pushup(rt);
}
void Update(int rt,int pos)
{
    if(tree[rt].L==tree[rt].R){
        ans[c--] =tree[rt].L;
        tree[rt].sum=0;
        return;
    }
    if(pos>tree[rson].sum){
        Update(lson,pos-tree[rson].sum);
    } else {
        Update(rson,pos);
    }
    Pushup(rt);
}
int main()
{
#ifdef zsc
    freopen("input.txt","r",stdin);
#endif
    int n,m,i;
    scanf("%d",&n);
    while(n--)
    {
        
        scanf("%d",&m);
        c=m;
        for(i=1;i<=m;++i){
            scanf("%d",&v[i]);
        }
        for(i=m;i>0;--i)v[i]=v[i]-v[i-1]+1;
        build(1,1,m);
        for(i=m;i>0;--i){
            Update(1,v[i]);
        }
        for(i=1;i<=m-1;++i){
            printf("%d ",ans[i]);
        }
        printf("%d\n",ans[m]);
    }
    return 0;
}


只是因为数组从0开始还是从1开始,就Wa了,真心无语。(发现错误了,原来是v【0】未加一。。。。)
WA代码:
 
 
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdio>
using namespace std;
#define lson (rt<<1)
#define rson (rt<<1|1)
#define T 50010
struct node
{
    int L,R,mid;
    int sum;
}tree[T<<2];
int v[T],ans[T],c;
void Pushup(int rt)
{
    tree[rt].sum = tree[lson].sum+tree[rson].sum;
}
void build(int rt,int L,int R)
{
    tree[rt].L = L,tree[rt].R = R;
    tree[rt].mid = (L+R)>>1;
    if(L==R){
        tree[rt].sum =1;
        return;
    }
    build(lson,L,tree[rt].mid);
    build(rson,tree[rt].mid+1,R);
    Pushup(rt);
}
void Update(int rt,int pos)
{
    if(tree[rt].L==tree[rt].R){
        ans[c--] =tree[rt].L;
        tree[rt].sum=0;
        return;
    }
    if(pos>tree[rson].sum){
        Update(lson,pos-tree[rson].sum);
    } else {
        Update(rson,pos);
    }
    Pushup(rt);
}
int main()
{
#ifdef zsc
    freopen("input.txt","r",stdin);
#endif
    int n,m,i;
    scanf("%d",&n);
    while(n--)
    {
        
        scanf("%d",&m);
        c=m;
        for(i=0;i<m;++i){
            scanf("%d",&v[i]);
        }
        for(i=m-1;i>0;--i)v[i]=v[i]-v[i-1]+1;
        build(1,1,m);
        for(i=m-1;i>=0;--i){
            Update(1,v[i]);
        }
        for(i=1;i<=m-1;++i){
            printf("%d ",ans[i]);
        }
        printf("%d\n",ans[m]);
    }
    return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值