排列 线段树

来源:互联网 发布:sql 小计 合计 编辑:程序博客网 时间:2024/06/13 16:42

额,昨天题目太难,所以没写总结,惭愧。最近老考线段树。

题目大意:给一段序列的逆序对前缀和,现在要求出这个序列;

分析:,不难看出从后往前推,i-p[i]就是这个数在前面排第几大,于是我们只需要找出序列中第几大的位置,放进去打个标记就好了,线段树维护。

# include <iostream># include <cstdio># include <cmath># include <list># include <cstring># include <map># include <ctime># include <algorithm># include <queue>using namespace std;typedef long long ll;int read(){    register int f=1,i=0;char ch=getchar();    while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}    while(ch>='0'&&ch<='9') {i=(i<<3)+(i<<1)+ch-'0';ch=getchar();}    return f*i;}int tr[100005<<2];ll n,m,p[100005],ans[100005];struct seg{    inline void change(int k){        tr[k]=tr[k<<1]+tr[k<<1|1];    }    inline void build(int k,int l,int r){        if(l==r){tr[k]=1;return ;}        int mid=l+r>>1;        build(k<<1,l,mid);build(k<<1|1,mid+1,r);        change(k);    }    inline int query(int k,int l,int r,int x){        if(l==r){tr[k]=0;return l;}        int mid=l+r>>1,tmp;        if(x<=tr[k<<1]) tmp=query(k<<1,l,mid,x);        else tmp=query(k<<1|1,mid+1,r,x-tr[k<<1]);        change(k);return tmp;    }}Seg;int main(){    n=read();    for(int i=1;i<=n;++i) p[i]=read();    for(int i=n;i;--i) p[i]-=p[i-1];    Seg.build(1,1,n);    for(int i=n;i;--i)        ans[i]=Seg.query(1,1,n,i-p[i]);    for(int i=1;i<=n;++i)        cout<<ans[i]<<" ";}
原创粉丝点击