Bestcoder round #65 && hdu 5592 ZYB's Premutation 线段树

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

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.

1≤T≤5,1≤N≤50000

Output

For each testcase,print the ans.

Sample Input

1

3

0 1 2

Sample Output

3 1 2

Source

BestCoder Round #65

思路:容易想到k = (a[i] - a[i - 1] + 1)就是原序列第i个数的左边比其大的个数,可以从右往左依次计算

用线段树实现:找出序列中第k个正数对应的下标位置,没找到一个,就相当于把该位置的数变为负数O(log)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <iostream>
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1|1
using namespace std;
const int INF = 0x3f3f3f3f;
typedef long long ll;

const int N = 50005;
int num[N << 2], a[N], ans[N];
void up(int rt) { num[rt] = num[rt << 1] + num[rt << 1|1]; }
void build(int l, int r, int rt)
{
    if(l == r) {
        num[rt] = 1;
        return ;
    }
    int m = (l + r) >> 1;
    build(lson);
    build(rson);
    up(rt);
}
void update(int l, int r, int rt, int p)
{
    if(l == p && r == p) {
        num[rt]--;
        return ;
    }
    int m = (l + r) >> 1;
    if(p <= m) update(lson, p);
    else update(rson, p);
    up(rt);
}
int pos;
void get(int l, int r, int rt, int x)
{
    if(l == r) {
        pos = l;
        return;
    }
    int m = (l + r) >> 1;
    if(num[rt << 1] < x) get(rson, x - num[rt << 1]);
    else get(lson, x);
}
int main()
{
    int _; scanf("%d", &_);
    while(_ --)
    {
        int n; scanf("%d", &n);
        for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        build(1, n, 1);
        int c = n;
        for(int i = n; i >= 2; --i)
        {
            int d = c - (a[i] - a[i - 1]);
            get(1, n, 1, d);
            update(1, n, 1, pos);
         //   cout << pos << endl;
            ans[i] = pos;
            c--;
        }
        get(1, n, 1, 1); ans[1] = pos;
        for(int i = 1; i < n; ++i) printf("%d ", ans[i]);
        printf("%d\n", ans[n]);
    }
    return 0;
}

Bestcoder round #65 && hdu 5592 ZYB's Premutation 线段树

时间: 2024-10-27 01:32:41

Bestcoder round #65 && hdu 5592 ZYB's Premutation 线段树的相关文章

Bestcoder round #65 &amp;&amp; hdu 5593 ZYB&#39;s Tree 树形dp

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 354    Accepted Submission(s): 100 Problem Description ZYB has a tree with N nodes,now he wants you to solve the numbers of nodes distanced no m

hdu 5592 ZYB&#39;s Premutation (线段树+二分查找)

链接: http://acm.hdu.edu.cn/showproblem.php?pid=5592 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

HDU 5592 ZYB&#39;s Premutation(树状数组+二分)

题意:给一个排列的每个前缀区间的逆序对数,让还原 原序列. 思路:考虑逆序对的意思,对于k = f[i] - f[i -1],就表示在第i个位置前面有k个比当前位置大的数,那么也就是:除了i后面的数字之外,它是在剩下的数字当中第k+1大的. 知道这个之后,可以用树状数组来帮助找出剩下的数中第k大的数,刚开始我们可以让1-n中每个元素都标记为1,那么他们的前缀和就代表它是第几小.所以,我们可以对于他们的和来二分快速寻找第k大数.其实在树状数组里面是按照第(i-k)小来找的.找完之后要删除这个元素的

BC 65 ZYB&#39;s Premutation (线段树+二分搜索)

题目简述:有一个全排列,一直每个前缀区间的逆序对数,还原这个排列. fi记录逆序对数,pi记录该位置数值,则k=fi-f(i-1)表示前i-1个数比pi大的数的个数,那么只要在剩余元素求出按大小顺序第i-k个数字即可. 线段树+二分搜索,线段树bit[i]记录i的在剩余元素的排名顺序. 1 /******************************* 2 3 Date : 2015-12-06 19:49:59 4 Author : WQJ ([email protected]) 5 Lin

HDU 5592 ZYB&#39;s Game 【树状数组】+【二分】

<题目链接> 题目大意: 给你一个由1~n,n个数组成的序列,给出他们每个的前缀逆序数,现在要求输出这个序列. 解题分析: 由前缀逆序数很容易能够得到每个数的逆序数.假设当前数是i,它前面比它小的数为a[i]( i - 1 - i的逆序数即可),我们不难知道,i在前i个数中是第i+1大的.然后我们从后往前考虑,每次都能确定一个位置的数的大小,根据当前位置i的数在 1~i 的数的大小,我们用二分查找快速聪当前还未分配的数中给它分配相应大小的数值,然后将这个数值从可分配的数中剔除,防止对前面的数造

BestCoder Round #65 (ZYB&#39;s Game)

ZYB's Game Accepts: 672 Submissions: 1207 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Description ZYBZYBZYB played a game named NumberBombNumber BombNumberBomb with his classmates in hiking:a host keeps a

hdu 5592 ZYB&#39;s Game 树状数组

ZYB's Game Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5592 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

[BestCoder Round #3] hdu 4909 String (状压,计数)

String Problem Description You hava a non-empty string which consists of lowercase English letters and may contain at most one '?'. Let's choose non-empty substring G from S (it can be G = S). A substring of a string is a continuous subsequence of th

[BestCoder Round #4] hdu 4932 Miaomiao&#39;s Geometry (贪心)

Miaomiao's Geometry Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 363    Accepted Submission(s): 92 Problem Description There are N point on X-axis . Miaomiao would like to cover them ALL by