zoukankan      html  css  js  c++  java
  • 【ybtoj高效进阶 21265】排队问题(fhq-Treap)(构造)

    排队问题

    题目链接:ybtoj高效进阶 21265

    题目大意

    给你每个人的身高和要求,每个人的身高都不同。
    每个人的要求是要它左边比他高的人或右边比他高的人个数是它给出的值。
    然后要你找出字典序最小的满足的身高序列。

    思路

    我们考虑把人按身高从小到大排序,然后我们不难想到如果把身高一样的排在一起,然后我们一起填,那这个时候,我们其实就是要它填入的位置左边或右边是它给出的值即可。

    首先判不可能的条件,即比它大的个数小于它的值。
    那接着我们会有两个可以放的位置,那由于要字典序最小,我们是从小到大放的,所以我们就调哪个靠左放哪个即可。
    那放我们考虑有点类似链表的插入,这里用的是 fhq-Treap。

    然后由于你要消除相同身高的影响,我们考虑先放位置后的,再放位置前的。
    所以你排个序就好了。

    代码

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    
    using namespace std;
    
    struct node {
    	int a, b;
    }a[100001];
    int n;
    
    bool cmp(node x, node y) {
    	if (x.a != y.a) return x.a > y.a;
    	return x.b > y.b;
    }
    
    struct fhq_treap {//平衡树
    	int rd[100001], ls[100001], rs[100001];
    	int a[100001], sz[100001], tot, root;
    	
    	int make_new(int val) {
    		int now = ++tot;
    		a[now] = val; sz[now] = 1;
    		ls[now] = rs[now] = 0;
    		rd[now] = rand();
    		return now;
    	}
    	
    	void up(int now) {
    		sz[now] = sz[ls[now]] + sz[rs[now]] + 1;
    	}
    	
    	int merge(int x, int y) {
    		if (!x || !y) return x + y;
    		
    		if (rd[x] > rd[y]) {
    			rs[x] = merge(rs[x], y);
    			up(x);
    			return x;
    		}
    		else {
    			ls[y] = merge(x, ls[y]);
    			up(y);
    			return y;
    		}
    	}
    	
    	pair <int, int> split_rnk(int now, int rnk) {
    		if (!now) return make_pair(0, 0);
    		if (!rnk) return make_pair(0, now);
    		
    		pair <int, int> re;
    		if (rnk <= sz[ls[now]]) {
    			re = split_rnk(ls[now], rnk);
    			ls[now] = re.second;
    			up(now);
    			re.second = now;
    		}
    		else {
    			re = split_rnk(rs[now], rnk - sz[ls[now]] - 1);
    			rs[now] = re.first;
    			up(now);
    			re.first = now;
    		}
    		return re;
    	}
    	
    	int insert(int val, int rnk) {
    		int now = make_new(val);
    		pair <int, int> re = split_rnk(root, rnk);
    		return merge(merge(re.first, now), re.second);
    	}
    	
    	void write(int now) {
    		if (!now) return ;
    		
    		write(ls[now]);
    		printf("%d ", a[now]);
    		write(rs[now]);
    	}
    }T;
    
    int main() {
    //	freopen("queue.in", "r", stdin);
    //	freopen("queue.out", "w", stdout);
    	
    	srand(1919810);
    	
    	scanf("%d", &n);
    	for (int i = 1; i <= n; i++)
    		scanf("%d %d", &a[i].a, &a[i].b);
    	
    	sort(a + 1, a + n + 1, cmp);
    	
    	for (int i = 1; i <= n; i++) {
    		int ii = i;
    		if (a[ii].b > i - 1) {//比它高的人没有那么多
    			printf("impossible");
    			return 0;
    		}
    		if ((i - 1) - a[ii].b < a[ii].b) a[ii].b = (i - 1) - a[ii].b;//反过来更前面
    		while (ii < n && a[ii + 1].a == a[ii].a) {//把相同的都找出来
    			ii++;
    			if (a[ii].b > i - 1) {//跟前面一个道理
    				printf("impossible");
    				return 0;
    			}
    			if ((i - 1) - a[ii].b < a[ii].b) a[ii].b = (i - 1) - a[ii].b;
    		}
    		sort(a + i, a + ii + 1, cmp);//重新排一次序,排出 b(因为你前面可能会改 b)
    		for (int j = i; j <= ii; j++) {//一个一个放
    			T.root = T.insert(a[j].a, a[j].b);
    		}
    		i = ii;
    	}
    	
    	T.write(T.root);
    	
    	return 0;
    }
    
  • 相关阅读:
    HTML和CSS之HTML(记录一2015.3.30)
    jquery学习记录三(表单选择器)
    jquery学习记录四(操作DOM元素)
    jquery学习记录二(过滤性选择器)
    jquery学习记录一(基础选择器)
    聚集索引和非聚集索引
    git命令
    4,gps信号与地图匹配算法
    3,gps定位原理及格式
    2,地图数据分析-地图数据转换成导航引擎数据
  • 原文地址:https://www.cnblogs.com/Sakura-TJH/p/YBTOJ_GXJJ_21265.html
Copyright © 2011-2022 走看看