hdu 5493线段树+模拟

来源:互联网 发布:固定资产投资的算法 编辑:程序博客网 时间:2024/05/17 23:45

点击打开链接


字典序最小 从高度最小的开始安排 尽量靠前排 

如果是前面有k个人 则第i个人排在第k+1个空位上

如果是后面有k个人 则第i个人排在第x+1个空位上

因为已经排好了前i-1个人 第i个人后面有k个空位置 第i个人也占了一个位置

则剩下的空位有n-(i-1)-k-1个 则x=n-i-k
 
字典序最小取k=min(k,x)即可  

因为放左边时 i+k<=n 放右边n-i-k>0 所以当i+k>n时无解

</pre><pre name="code" class="cpp">#include <iostream>#include <algorithm>#include <cstring>using namespace std;const int M=1e5+20;int n,ans[M];struct Node{int h;int num;// 前面或后面有num个比它高 }node[M];bool cmp(const Node &a,const Node &b){return a.h<b.h; }int seg[M<<2];void pushup(int rt){seg[rt]=seg[rt<<1]+seg[rt<<1|1];}void build(int l,int r,int rt){if(l==r){seg[rt]=1;return;}int m=(l+r)>>1;build(l,m,rt<<1);build(m+1,r,rt<<1|1);pushup(rt);}void update(int p,int h,int l,int r,int rt){if(l==r){seg[rt]=0; ans[l]=h; return;}int m=(l+r)>>1;if(seg[rt<<1]>=p) {update(p,h,l,m,rt<<1);}else//放到右子树记得要减去左边的空位数 {update(p-seg[rt<<1],h,m+1,r,rt<<1|1);}pushup(rt);}int main(){int t;cin>>t;for(int cas=1;cas<=t;cas++){cin>>n;build(1,n,1);for(int i=1;i<=n;i++){scanf("%d%d",&node[i].h,&node[i].num);}sort(node+1,node+1+n,cmp);//字典序最小 从高度最小的开始安排 尽量靠前排 int flag=1;for(int i=1;i<=n;i++){// 如果是前面有k个人 则第i个人排在第k+1个空位上// 如果是后面有k个人 则第i个人排在第x+1个空位上,//因为已经排好了前i-1个人 第i个人后面有k个空位置 第i个人也占了一个位置//则剩下的空位有n-(i-1)-k-1个 则x=n-i-k  //字典序最小取min(k,x)即可  //因为放左边时 i+k<=n 放右边n-i-k>0 所以i+k>n时无解if(i+node[i].num>n){flag=0;break; }//cout<<seg[1]<<endl; int k=min(node[i].num,n-i-node[i].num)+1;//第i个人放在第k个空位update(k,node[i].h,1,n,1);} printf("Case #%d: ",cas);if(!flag){printf("impossible\n");continue;}for(int i=1;i<=n;i++){printf("%d",ans[i]);if(i<n)cout<<" ";elsecout<<endl;}}return 0;}


0 0
原创粉丝点击