线段树 - ZYB's Premutation

线段树 - ZYB's Premutation

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.

 
     

1 <= T <= 51,1 <= N <= 50000.

 
     

Output
For each testcase,print the ans.

 
     

Sample Input
1
3
0 1 2

 
     

Sample Output
3 1 2



----------------------------------------我是分割线^_^-------------------------------------------


又是一道线段树的题目,普通方法也可以做,只不过肯定超时了,因为用线段树进行优化之后都差点超时= =,
又是逆序数,题目意思是说给出逆序数对数的前缀和,然后让你求出原序列,查看题解后你会发现一个规律:
题目给出的Ai,可以通过与前一项相减获得第i个数在1到n的第几大蛇王位置,第i个数为A(i) - A(i-1) + 1
大,括号中的数为下标,然后通过线段树找得到这个数在剩下的为筛选出去的数中的第几大的位置。


#include<iostream>
#include<algorithm>
#include<cstring> #include<cstdio> #include<cmath> #include<string> #include<queue> #include<vector> #include<cctype> #include<set> #include<map> #include<sstream> using namespace std; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define INF 0x3f3f3f3f #define Int __int64 #define pii pair<int,int> const int MAXN = 55555; int sum[MAXN<<2]; int num[MAXN]; int ans[MAXN]; void PushUp(int rt) { sum[rt] = sum[rt<<1] + sum[rt<<1|1]; } void Build(int l, int r, int rt) { if (l == r) { sum[rt] = 1; return ; } int m = (l + r)>>1; Build(lson); Build(rson); PushUp(rt); } void UpDate(int pos, int l, int r, int rt) { if (l == r) { sum[rt] = 0; return ; } int m = (l + r)>>1; if (pos <= m) UpDate(pos, lson); else UpDate(pos, rson); PushUp(rt); } int Query(int value, int l, int r, int rt) { if (l == r) { return r; } int ret; int m = (l + r)>>1; if (value - sum[rt<<1|1] > 0) ret = Query(value - sum[rt<<1|1], lson);/*注意理解这里,
  如果第几大的位置超过右边的范围了,就去左边找*/ else ret = Query(value, rson); return ret; } int
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值