正题
题目大意
给出每个人前或后面比他高的人数,然后求一个序列,人们高度字典序最小的序列。
解题思路
我们将高度从小到大插入,然后对于每个人至少保留一些比他高的人的空位,然后用权值线段树O(log2n)O(log^2 n)O(log2n)计算第k个空位的位置插入。
当然也有二分加树状数组,详见
https://blog.csdn.net/Mr_wuyongcong/article/details/81988835
code
#include<cstdio>
#include<algorithm>
#define N 100010
using namespace std;
struct node{int h,num;
}a[N];
struct treenode{int l,r,w;
}tree[N*8];
int n,put[N];
bool cmp(node x,node y)
{return x.h<y.h;}
int read(){int x=0,flag=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*flag;
}
void write(int x)
{if(x>9) write(x/10);putchar(x%10+48);return;
}
void build(int k,int l,int r)//建树
{tree[k].l=l;tree[k].r=r;tree[k].w=r-l+1;if(l==r) return;int mid=(l+r)/2;build(k*2,l,mid);build(k*2+1,mid+1,r);
}
void inster(int k,int num,int i)//第num个空位
{tree[k].w--;if(tree[k].l==tree[k].r){put[tree[k].l]=i;return;}if(tree[k*2].w>=num) inster(k*2,num,i);else inster(k*2+1,num-tree[k*2].w,i);
}
int main()
{n=read();for(int i=1;i<=n;i++)a[i].h=read(),a[i].num=read();sort(a+1,a+1+n,cmp);for(int i=1;i<=n;i++)if(a[i].num>=n-i+1){printf("impossible");return 0;}build(1,1,n);for(int i=1;i<=n;i++){int k=min(a[i].num+1,n-a[i].num-i+1);//计算最小字典序的位置inster(1,k,a[i].h);}for(int i=1;i<=n;i++)write(put[i]),putchar(' ');
}