数字的字典序,,有点迷,网上看题解也没有明说,总之越大的数字放在后面就行了
利用二分找到前k个空位即可
/* 每个人有一个独特的高度,第i个人高hi,前面有ki个人比他高或后面有ki个人比他高 请求出可能队列, 升序排列身高,每个人可选的位置是第k+1个空位或者第n-i-k个空位, 如果n-i-k<=0,那么就是impossible 结果要按照字典序输出,所以如果有两个可选位置可以插入时,需要判断从前往后插还是从后往前插好。 插入时按照二分找到树状数组中第k+1个空位 离线离散化,树状数组维护空位 复杂度O(nlognlogn) */ #include<bits/stdc++.h> #define maxn 100005 using namespace std; struct node{int h,k;}p[maxn]; int cmp(node a,node b){return a.h<b.h;} int bit[maxn],ans[maxn],n; void add(int x,int num){ for(int i=x;i<=n;i+=i&-i) bit[i]+=num; } int query(int x){ int res=0; for(int i=x;i;i-=i&-i) res+=bit[i]; return res; } int main(){ int t,flag; scanf("%d",&t); for(int tt=1;tt<=t;tt++){ scanf("%d",&n); memset(bit,0,sizeof bit); flag=0; for(int i=1;i<=n;i++) add(i,1); for(int i=1;i<=n;i++)scanf("%d%d",&p[i].h,&p[i].k); sort(p+1,p+1+n,cmp); for(int i=1;i<=n;i++){ int pos1=p[i].k+1,pos2=n-i-p[i].k+1; if(pos2<=0){ flag=1; break; } int pos=min(pos1,pos2);//为了字典序最小找一个最小的位置 int l=1,r=n,mid,anss; while(l<=r){ mid=l+r>>1; if(query(mid)<pos) l=mid+1; else anss=mid,r=mid-1; } add(anss,-1); ans[anss]=p[i].h; } if(flag)printf("Case #%d: impossible ",tt); else { printf("Case #%d:",tt); for(int i=1;i<=n;i++) printf(" %d",ans[i]); puts(""); } } return 0; }