题目大意:
一些人,每个人的身高都是不一样的
然后再给你一个k,表示这个人的左边或者右边,有k个人比他高
然后让你构造一个满足条件且字典序最小的序列
思路:
按照权值排序 这样每次加进去后只有后面的才会比它大
加的时候需要在前面或后面留出k个空间
选出位置靠前的那个加入使字典序最小
如果两个位置都被占即无解
然后用线段树维护一下区间和即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 100100 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 int n,sum[MAXN<<2],ans[MAXN]; 21 struct data 22 { 23 int val,k; 24 bool operator < (const data &a) const 25 { 26 return val<a.val; 27 } 28 }g[MAXN]; 29 void build(int k,int l,int r) 30 { 31 sum[k]=r-l+1; 32 if(l==r) return ; 33 int mid=(l+r)>>1; 34 build(k<<1,l,mid);build(k<<1|1,mid+1,r); 35 } 36 int mdf(int k,int x,int l,int r) 37 { 38 sum[k]--; 39 if(l==r) 40 if(sum[k]+1) return l; 41 else return 0; 42 int mid=(l+r)>>1; 43 if(x<=sum[k<<1]) return mdf(k<<1,x,l,mid); 44 else return mdf(k<<1|1,x-sum[k<<1],mid+1,r); 45 } 46 int main() 47 { 48 int T=read(); 49 for(int t=1;t<=T;t++) 50 { 51 printf("Case #%d: ",t); 52 n=read(); 53 for(int i=1;i<=n;i++) g[i].val=read(),g[i].k=read()+1; 54 sort(g+1,g+n+1); 55 build(1,1,n); 56 for(int i=1,r=n,x,y;i<=n;i++,r--) 57 { 58 if((x=mdf(1,min(g[i].k,r-g[i].k+1),1,n))&&min(g[i].k,r-g[i].k+1)>=1&&min(g[i].k,r-g[i].k+1)<=r) ans[x]=g[i].val; 59 else if(y=mdf(1,max(g[i].k,r-g[i].k+1),1,n)&&min(g[i].k,r-g[i].k+1)>=1&&min(g[i].k,r-g[i].k+1)<=r) ans[y]=g[i].val; 60 else {puts("impossible");goto ed;} 61 } 62 for(int i=1;i<n;i++) printf("%d ",ans[i]);printf("%d ",ans[n]); 63 ed:; 64 } 65 }