BestCode_Round65_C题(线段树)

来源:互联网 发布:二年级体测数据 编辑:程序博客网 时间:2024/06/07 04:05

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

思路:很容易处理出当前位置前面比当前位置的数大的数的个数。假设前缀逆序对数为num[i] , 则num[i]-num[i-1]就为位置i前面比原本在位置i上的数大的个数。

假设最后一个数为N. 则[1-N]中比位置N更大的数为num[N]-num[N-1] ,则第N个位置的数就为 N - (num[N]-num[N-1]).(在[1,N]中第N - (num[N]-num[N-1])大的数)

第N-1个位置的数为 除去第N个位置已经求出来的数外在[1,N]中第(N-1) - (num[N-1]-num[N-2])大的数(这个数用线段树求解)


#include <iostream>#include <cstdio>#include <algorithm>#define bug1 printf("bug1\n")#define lson rt<<1#define rson rt<<1|1using namespace std;const int maxx = 50010;struct stree{    int l;    int r;    int val;}a[maxx*4];void push_up(int rt){    a[rt].val = a[lson].val + a[rson].val;}void build(int rt,int l,int r){    a[rt].l = l;    a[rt].r = r;    if(l == r){        a[rt].val = 1;        return ;    }    int mid = (l+r)>>1;    build(lson,l,mid);    build(rson,mid+1,r);    push_up(rt);}void update(int rt,int k){    if(a[rt].l == a[rt].r){        a[rt].val = 0;        return ;    }    int mid = (a[rt].l + a[rt].r)>>1;    if(k<=mid) update(lson,k);    else update(rson,k);    push_up(rt);}int query(int rt,int k){   if(a[rt].l==a[rt].r){        return a[rt].l;   }   int mid = (a[rt].l+a[rt].r)>>1;   if(a[lson].val>=k) return query(lson,k);   else return query(rson,k-a[lson].val);}int T, N;int ans[maxx];int num[maxx];int main( ){    cin>>T;    num[0] = 0;    while(T--){        cin>>N;        build(1,1,N);        for(int i = 1;i <= N; ++i){            scanf("%d",&num[i]);        }        for(int i = N;i >= 1; --i){            num[i]=num[i]-num[i-1];        }        for(int i = N; i >= 1; --i){            ans[i] = query(1,i-num[i]);            update(1,ans[i]);        }        for(int i = 1;i < N; ++i){            printf("%d ",ans[i]);        }        printf("%d\n",ans[N]);    }    return 0;}

如有BUG欢迎指出~~~

EMAIL: hh_0828@outlook.com

0 0