ACM学习历程—HDU5592 ZYB's Premutation(逆序数 && 树状数组 && 二分)(BestCoder Round #65 1003)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5592

题目大意就是给了每个[1, i]区间逆序对的个数,要求复原原序列。

比赛的时候2B了一发。

首先既然给了[1, i-1][1, i]区间逆序对的个数,自然可以求出与i组成逆序对的个数,自然就是i前面比i大的个数,自然也就能求出i前面比i小的个数。

然后我考虑最后一个数,由于它在最后一个,所以所有数都在它前面,自然如果知道它前面有多少个比他小的,就知道它是几了。不妨设最后一个是p,然后考虑倒数第二个,如果它前面有x个比他小的,那么倒数第二个自然是除掉p以外排在x+1位置上的那个数。以此类推。

有了这个需要数据结构的支持,可以用树状数组维护[1, n]区间1的个数,然后一旦找到某个数,就让它置0。然后找当前位置前面有x个数比他小,即在树状数组中前缀和为x+1的那个区间右值,此处我采用了二分查找。

代码:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <set>
#include <map>
#include <queue>
#include <string>
#define LL long long

using namespace std;

const int maxN = 50005;
int n, ans[maxN];
int a[maxN];
int d[maxN];

int lowbit(int x)
{
    return x&(-x);
}

void add(int id, int pls)
{
    while(id <= maxN)//id×î´óÊÇmaxN
    {
        d[id] += pls;
        id += lowbit(id);
    }
}

int sum(int to)
{
    int s = 0;
    while(to > 0)
    {
        s = s + d[to];
        to -= lowbit(to);
    }
    return s;
}

void input()
{
    memset(d, 0, sizeof(d));
    scanf("%d", &n);
    int pre, now;
    pre = 0;
    for (int i = 1; i <= n; ++i)
    {
        scanf("%d", &now);
        a[i] = i-1-(now-pre);
        pre = now;
    }
}

int cal(int k)
{
    int lt = 1, rt = n, mid, t;
    while (lt+1 < rt)
    {
        mid = (lt+rt)>>1;
        t = sum(mid);
        if (t >= k) rt = mid;
        else lt = mid;
    }
    if (sum(lt) == k) return lt;
    else return rt;
}

void work()
{
    for (int i = 1; i <= n; ++i)
        add(i, 1);
    for (int i = n; i > 0; --i)
    {
        ans[i] = cal(a[i]+1);
        add(ans[i], -1);
    }
    for (int i = 1; i <= n; ++i)
    {
        if (i != 1) printf(" ");
        printf("%d", ans[i]);
    }
    printf("\n");
}

int main()
{
    //freopen("test.in", "r", stdin);
    int T;
    scanf("%d", &T);
    for (int times = 1; times <= T; ++times)
    {
        input();
        work();
    }
    return 0;
}
View Code

 

posted on 2015-12-05 22:20  AndyQsmart  阅读(571)  评论(0编辑  收藏  举报

导航