HDU 5592 ZYB's Premutation

来源:互联网 发布:天刀天香御姐捏脸数据 编辑:程序博客网 时间:2024/06/07 03:39

题目链接

传送门

题意

对于一个一到n的序列,给出他的逆序数的前缀和,求这个序列。

分析

我们倒着来考虑,a[1]a[n]的逆序数为sum[n],那么sum[n]sum[n1]=k表示的是a[1]a[n1]有k个数大于a[n]那么a[n]就是这个序列的第k+1大的数,题目就转化成求数组的动态第k大。

Code

#include <cstdio>#include <cstring>#include <algorithm>#include <vector>#define lson num<<1#define rson num<<1|1#define gl l,m,lson#define gr m+1,r,rson#define PARA int l,int r,int numusing namespace std;const int MAXN = 5e4+100;struct SegTree {    int st[MAXN<<2];    void init() {        memset(st,0,sizeof(st));    }    void update(int pos,int v,PARA) {        int m = l+r>>1;        if(l==r)            st[num]+=v;        else {            if(m>=pos)                update(pos,v,gl);            else                update(pos,v,gr);            st[num]=st[lson]+st[rson];        }    }    int find(int k,PARA) {        if(l==r)            return l;        int m = l + r >> 1;        if(st[rson]>=k)            return find(k,gr);        else            return find(k-st[rson],gl);    }} S;int a[MAXN];int main() {    int t,n;    scanf("%d",&t);    while(t--) {        scanf("%d",&n);        S.init();        a[0]=0;        for(int i=1; i<=n; i++) {            scanf("%d",a+i);            S.update(i,1,1,n,1);        }        vector<int >ans;        for(int i=n; i>=1; i--) {            int k=a[i]-a[i-1]+1;            int val=S.find(k,1,n,1);            ans.push_back(val);            S.update(val,-1,1,n,1);        }        for(int i=n-1; i>0; i--)            printf("%d ",ans[i]);        printf("%d\n",ans[0]);    }    return 0;}
1 0
原创粉丝点击