ZYB's Premutation(挺简单的数据结构题目)

ZYB's Premutation

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


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

题意: HDU上有中文题面,题意我就不呵呵了
题解: 很容易想到,从数组后面往前推,因为最后一个数我们可以确定其位置,接下来就是代码优化问题。直接暴力跑的话是会超时的。这题我用的是二分位置,加区间树状数组验证答案。

AC代码:
import java.util.*;
import java.io.*;

public class main{
	
	static Scanner cin = new Scanner(System.in);
	static PrintWriter out = new PrintWriter(System.out);
	static int[] a = new int[50005];
	static int[] c = new int[50005];
	static int n;
	
	public static void main(String[] args) throws IOException{
		int T = cin.nextInt();
		while(T-- > 0) {
			int pre = -1,now;
			n = cin.nextInt();
			for(int i = 1; i <= n; i++) {
				a[i] = cin.nextInt();
				if(pre == -1) pre = a[i];
				else {
					now = a[i] - pre; 
					pre = a[i];
					a[i] = now; 
				}
			}
			Arrays.fill(c, 0);
			for(int i = n; i >= 1; i--) {
				int l = 1,r = n,ans = 0;
				while(l <= r) {
					int mid = l + r >> 1;
					int tp = n - mid - que(mid + 1, n);
					if(tp > a[i] || tp == a[i] && que(mid, mid) == 0) {
						ans = mid;
						l = mid + 1;
					} else {
						r = mid - 1;
					}
				}
				a[i] = ans;
				add(ans);
			}
			boolean ok = false;
			for(int i = 1; i <= n; i++) {
				if(ok) System.out.print(' ');
				else ok = true;
				System.out.print(a[i]);
			}
			System.out.println();
		}
	}
	public static void add(int x) {
		while(x <= n) {
			c[x]++;
			x += x & -x;
		}
	}
	public static int que(int l,int r) {
		int s = 0;
		if(l > r) return s;
		while(r > 0) {
			s += c[r];
			r -= r & -r;
		}
		l--;
		while(l > 0) {
			s -= c[l];
			l -= l & -l;
		}
		return s;
	}
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值