HDU 5592 ZYB's Premutation

題目鏈接

傳送門

題意

對於一個一到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 num
using 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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章