排列 线段树

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

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

分析:,不难看出从后往前推,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]<<" ";
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值