HDU5592-ZYB's Premutation

ZYB's Premutation

                                                                    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
                                                                                            Total Submission(s): 1085    Accepted Submission(s): 569


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
  
  
1 3 0 1 2
 

Sample Output
  
  
3 1 2
 

Source
 

Recommend
hujie
 


题意:有一个序列,现在知道这个序列所有前缀的逆序对数,还原出这个序列

解题思路:a[i]-a[i-1]表示第i个数前面比它大的数字个数。用i-(a[i]-a[i-1])表示i个数中比第i个数小的个数,倒着跑,线段树维护每个区间还剩多少数字


#include <iostream>  
#include <cstdio>  
#include <string>  
#include <cstring>  
#include <cmath> 
#include <algorithm>
#include <queue>  
#include <vector>  
#include <set>  
#include <stack>  
#include <map>  
#include <climits>  

using namespace std;

#define LL long long  
const int INF = 0x3f3f3f3f;

int t, n;
int a[50009], sum[50009 << 2], ans[50009];

void build(int k, int l, int r)
{
	sum[k] = r - l + 1;
	if (l == r) return;
	int mid = (l + r) >> 1;
	build(k << 1, l, mid), build(k << 1 | 1, mid + 1, r);
}

int query(int k, int l, int r, int p)
{
	sum[k]--;
	if (l == r) return l;
	int mid = (l + r) >> 1;
	if (sum[k << 1] >= p) return query(k << 1, l, mid, p);
	else return query(k << 1 | 1, mid + 1, r, p - sum[k << 1]);
}

int main()
{
	scanf("%d", &t);
	while (t--)
	{
		scanf("%d", &n);
		a[0] = 0;
		for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
		build(1, 1, n);
		for (int i = n, j = 0; i >= 1; i--, j++)
		{
			int p = a[i] - a[i - 1] + 1;
			p = n - j - p + 1;
			ans[n - j] = query(1, 1, n, p);
		}
		printf("%d", ans[1]);
		for (int i = 2; i <= n; i++) printf(" %d", ans[i]);
		printf("\n");
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值