hdu 5493 Queue(逆序对,线段树)

来源:互联网 发布:南宁知远科技有限公司 编辑:程序博客网 时间:2024/05/21 17:04

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5493

解题思路:

一道线段树的题目,因为是前面或者后面有k个比自己高的人,所以我们应该按照由身高从小到大排序,这样前面的人对后面的人就没有什么影响。我们线段树中存的是每一段有多少空位置。这样每次如果根节点的空位置小于k,那么很明显没办法放,同样因为前面对后面的没有什么影响,我只需要找到k和n-k-i中较小的,如果这个值小于0,那么则没有办法继续插入。因为满足字典序最小,因此往最前面位置插入就可以了。


#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 100005;struct Node{int h,k;bool operator < (const Node &rhs) const{return h < rhs.h;}}p[maxn];struct Seg{int l,r,sum;}tree[maxn<<2];int n,res[maxn];void build(int rt,int l,int r){tree[rt].l = l, tree[rt].r = r;tree[rt].sum = r - l + 1;if(l == r) return;int mid = (l + r) >> 1;build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);}void update(int rt,int k,int val){if(tree[rt].l == tree[rt].r){res[tree[rt].l] = val;tree[rt].sum = 0;return;}if(tree[rt<<1].sum >= k) update(rt<<1,k,val);else update(rt<<1|1,k - tree[rt<<1].sum,val);tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;}int main(){int t,cas = 1;scanf("%d",&t);while(t--){scanf("%d",&n);for(int i = 1; i <= n; i++)scanf("%d %d",&p[i].h,&p[i].k);sort(p+1,p+1+n);build(1,1,n);bool flag = true;for(int i = 1; i <= n; i++){int tmp = min(p[i].k,n - i - p[i].k); //判断是否是比前面大的有k个,还是后面大的有k个if(tmp < 0) {flag = false;break;}if(p[i].k < n - i - p[i].k)update(1,p[i].k + 1,p[i].h);else update(1,n - i - p[i].k + 1,p[i].h);}printf("Case #%d: ",cas++);if(flag == false) printf("impossible\n");else {for(int i = 1; i < n; i++)printf("%d ",res[i]);printf("%d\n",res[n]);}}return 0;}


0 0
原创粉丝点击