HDU 5592 ZYB's Premutation

本文详细介绍了如何使用线段树优化算法解决逆序数问题,通过匹配逆序对来重构原始序列,适用于大规模数据处理场景。

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

Problem Description

ZYBZYB has a premutation PP,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)(i,j)(i<j) is considered as a reverse log if A_i>A_jAi>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 NN.

In the next line there are NN numbers A_iAi,describe the number of the reverse logs of each prefix,

The input is correct.

1 \leq T \leq 51T5,1 \leq N \leq 500001N50000

Output

For each testcase,print the ans.

Sample Input
1
3
0 1 2
Sample Output

3 1 2

根据逆序数求原序列,线段树优化一下

#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 5;
int T, n, m, a[maxn], b[maxn], ans[maxn];

struct ST
{
    int f[maxn * 5];
    void build(int x,int l,int r)
    {
        if (l == r) f[x] = 1;
        else
        {
            int mid = l + r >> 1;
            build(x + x, l, mid);
            build(x + x + 1, mid + 1, r);
            f[x] = f[x + x] + f[x + x + 1];
        }
    }
    int find(int x, int l, int r, int v)
    {
        if (l == r) { f[x]--; return l; }
        else
        {
            int mid = l + r >> 1;
            f[x]--;
            if (v > f[x + x + 1]) return find(x + x, l, mid, v - f[x + x + 1]);
            else return find(x + x + 1, mid + 1, r, v);
        }
    }
}st;

int main()
{
    scanf("%d", &T);
    while (T--)
    {
        scanf("%d", &n);
        a[0] = 0;
        st.build(1, 1, n);
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
            b[i] = a[i] - a[i - 1];
        }
        for (int i = n; i; i--)
        {
            ans[i] = st.find(1, 1, n, b[i] + 1);
        }
        for (int i = 1; i <= n; i++) printf("%d%s", ans[i], i == n ? "\n" : " ");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值