hdu 5592 ZYB'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.

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:

the first line there is one number N.

1T100000,1N10000000

Output

For each testcase,print the ans.

Sample Input

1
3
0 1 2

Sample Output

3 1 2

HINT

题意

 

题解:

很显然可以发现,a[i]-a[i-1],就表示在[1,i]中比i大的数有多少个

那么我们倒着做就好了,拿一个树状数组来维护就行了~

代码:

#include<iostream>
#include<stdio.h>
#include<cstring>
using namespace std;
#define maxn 50005
long long a[maxn];
int ans[maxn];
#define lowbit(x) ((x)&(-x))

struct BinaryIndexTree
{
    int val[maxn],sz;

    void init(int sz){
        this->sz=sz;
        memset(val , 0 , sizeof(int)*(sz+5));
    }

    void updata(int pos ,int key){
        while(pos<=sz){
            val[pos]+=key;
            pos+=lowbit(pos);
        }
    }

    long long prefixsum(int pos){
        long long res=0;
        while(pos>0){
            res+=val[pos];
            pos-=lowbit(pos);
        }
        return res;
    }

    int query(int l,int r){
        return prefixsum(r)-prefixsum(l-1);
    }

    //到第一个大于等于k的位置返回
    //若不存在,返回-1
    int lower_bound(long long k){
        if(prefixsum(sz)<k) return -1;
        int l = 1 , r = sz;
        while(l <= r){
            int mid = l + ((r-l)>>1);
            if(prefixsum(mid) < k) l = mid + 1;
            else r = mid - 1;
        }
        return l;
       }

}solver;

long long c[maxn];
int main()
{
    int t;scanf("%d",&t);
    for(int cas=1;cas<=t;cas++)
    {
        memset(a,0,sizeof(a));
        memset(c,0,sizeof(c));
        int n;scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%I64d",&a[i]);
        for(int i=1;i<=n;i++)
            c[i]=a[i]-a[i-1];
        solver.init(n);
        for(int i=1;i<=n;i++)
            solver.updata(i,1);
        int tmp = 0;
        for(int i=n;i>=1;i--)
        {
            ans[i]=solver.lower_bound(n-tmp-c[i]);
            solver.updata(ans[i],-1);
            tmp++;
        }
        for(int i=1;i<=n;i++)
        {
            if(i!=n)
                printf("%d ",ans[i]);
            else printf("%d
",ans[i]);
        }
    }
}
原文地址:https://www.cnblogs.com/qscqesze/p/5023329.html