zoukankan      html  css  js  c++  java
  • 【题解】【LuoguP5894】【IOI2013】robots

    【题解】【LuoguP5894】【IOI2013】robots

    题目链接

    点击打开链接

    题目解法

    题目等价于一些点在平面上,一个机器人可以取走做平面或下平面的所有点,一轮一个机器人只能取一次。求最少多少次才能把所有点都取走。

    先二分多少次可以把所有点都去走。那么每个机器人取的次数 (le m) 。考虑贪心。将所有点用 (x) 轴排序,从可取得范围小到可取得范围大考虑所有可以取左平面的机器人。对于每个机器人,很明显先取(y) 坐标大得机器人。再考虑所有取下平面得机器人即可。

    那么需要做以下几件事情:

    1. 首先判断是否无解。
    2. 将所有左平面机器人、右平面机器人按照可取范围大小从小到大排序。
    3. 将所有点按照 (x) 轴排序。
    4. 二分取的次数 (m)
    5. 从小到大枚举所有取左平面的机器人,对于当前机器人 (a_i) ,把所有 (a_i) 可取的点按照 (y) 轴的顺序插入到一个堆里。取最靠上的 (m) 个点。
    6. 剩下一大堆取下平面的机器人。从可以取的部分少的机器人到多的机器人,每次取最靠下并且可取的 (m) 个机器人即可。

    总结

    • 本来以为二分并没有意义。但实际上二分有意义的。因为机器人的操作交换也没有问题,所以二分一个数 (m) 的意义就是可以将一个机器人的所有操作一起做了,而不用做一个操作换一个机器人。

    代码

    这次注意开 long long 了。

    #include <cstdio>
    #include <algorithm>
    #include <queue>
    #include <set>
    using namespace std;
    typedef long long ll;
    const int CT = 1e6 + 5, CAB = 5e4 + 5;
    int a, b, t, X[CAB], Y[CAB];
    struct Toy {
    	int w, s;
    	Toy(int _w = 0, int _s = 0) : w(_w), s(_s) {}
    } toy[CT];
    bool cmp(const Toy &x, const Toy &y) { return x.w < y.w; }
    struct cmp1 {
    	bool operator()(const Toy &x, const Toy &y) { return x.s < y.s; }
    	//如果函数返回值是 1,那么 y在上面 
    };
    priority_queue<Toy, vector<Toy>, cmp1> H1;
    int que[CT];
    bool check(int ans) {
    	while (!H1.empty()) H1.pop();
    	int pt = 1;
    	for (int i = 1; i <= a; ++i) {
    		while (pt <= t && toy[pt].w < X[i]) {
    			H1.push(toy[pt]);
    			++pt;
    		}
    		for (int j = 1; j <= ans; ++j) {
    			if (H1.empty()) break ; //这个地方开始写成了 !H1.empty() 
    			H1.pop();
    		}
    	}
    	//还可能有一些根本没有被塞进去的点(就是没有一个x[i]的机器人能消灭他),这里得加上 
    	for (int i = pt; i <= t; ++i)
    		H1.push(toy[i]);
    	int tail = 0;
    	while (!H1.empty()) {
    		que[++tail] = H1.top().s;
    		H1.pop();
    	}
    	sort(que + 1, que + tail + 1);
    	pt = 1;
    	for (int i = 1; i <= b; ++i) {
    		int cnt = 0;
    		while (pt <= tail && que[pt] < Y[i] && cnt < ans) {
    			++cnt;
    			++pt;
    		}
    	}
    	if (pt == tail + 1) return 1;
    	else return 0;
    }
    int main() {
    	scanf("%d%d%d", &a, &b, &t);
    	for (int i = 1; i <= a; ++i) scanf("%d", &X[i]);
    	for (int i = 1; i <= b; ++i) scanf("%d", &Y[i]);
    	sort(X + 1, X + a + 1);
    	sort(Y + 1, Y + b + 1);
    	for (int i = 1; i <= t; ++i) {
    		scanf("%d%d", &toy[i].w, &toy[i].s);
    		if (X[a] <= toy[i].w && Y[b] <= toy[i].s) {
    			printf("-1
    ");
    			return 0;
    		}
    	}
    	sort(toy + 1, toy + t + 1, cmp);
    	int L = 1, R = 1e6, ans;
    	while (L <= R) {
    		int mid = (L + R) >> 1;
    		if (check(mid)) {
    			ans = mid;
    			R = mid - 1;
    		} else
    			L = mid + 1;
    	}
    	printf("%d
    ", ans);
    	return 0;
    }
    
  • 相关阅读:
    JavaScript--截取字符串
    C#--Dictionary字典学习
    根据条件把A表数据更新到B表中一个字段中(查询更新)
    zip多文件的压缩下载和解压
    C# 创建一个新的DataTable,并根据查询的DataTable结果进行重新赋值
    C# string.formate() 中 如何使用string 循环出来的一串字符
    asp.net mvc 之jqgird 列表数据 根据字典显示中文
    asp.net mvc 之显示24小时折线对比数据
    hightchart扇形图asp.net mvc 实现
    hightchart单个柱状图实现之asp.net mvc
  • 原文地址:https://www.cnblogs.com/YouthRhythms/p/13363830.html
Copyright © 2011-2022 走看看