• 启智树冲省队组Day4T3 疏散


    一栋大楼中 (10^5) 个人紧急疏散。大楼可以被视作网格图(正视图),有三个区域,由两个宽为 1 的楼道隔开。走出楼道最下面即为离开。同一时刻一个位置只能有一个人。左右区域的人不能互相串。每个人每一秒能移动一格。问所有人离开所需的最小时间

    这题正解比暴力好写(一般贪心题都这样),因此考场上没想到贪心就很难受。

    首先考虑中间没有人的情况。这是个经典套路了。我们可以把每个人单独的花费时间算出来,然后如果花费时间相同,则它们会冲突,需要让一个人的时间 + 1;如果还出现相同,就继续 + 1,直到没有相同的为止。这个可以用并查集来维护。

    然后考虑中间有人的情况。如果人非常少,那么我们可以暴力枚举每个人去左边还是去右边。

    现在考虑一般情况。考虑到这道题实际上是要求“最晚走的人的走的时间最小”,于是考虑二分答案,保证每个人的时间都在 (mid) 以内即可。我们设 (L_i) 表示第 (i) 个人去左边的时间,(R_i) 表示第 (i) 个人去右边的时间。然后我们将所有人按照 (R_i) 从大到小排序,如果能去左边就尽量去左边,否则去右边

    感性证明:显然时间小更优,那么以后的所有人对于“去右边”都比当前这个人优。如果能够把当前这个人安排到左边,那么就算以后有个人也想安排到左边被占了,他还可以来右边,并且肯定比当前这个人的选择更多。

    看来,“想不到怎么贪心就排个序”的方法还是挺有用的。

    另外,此题的离散化也需要一些小技巧。暴力的 (n^2) 离散化显然不行,直接用 (map) 也感觉多个 (log) 不太稳(或许也可以手写 unordered_map)。考虑到有用的值只可能是计算出来的时间或者计算出来的时间 + 一些人数。我们可以把最劣情况模拟一遍,搞出所有的有用时间点,并且中间还需要空一些格子。显然,这样的时间点数量不会超过 (4n)。不太好描述,直接看代码吧:

    inline void lsh() {
    	sort(h + 1, h + 1 + htot);
    	int nw = 0;
    	for (register int i = 1; i <= htot; ++i) {
    		if (h[i] <= nw + 1)	++nw, lh[++ltot] = nw;
    		else	++nw, lh[++ltot] = nw, nw = h[i], lh[++ltot] = nw;
    	}
    	for (register int i = 1; i <= n; ++i)
    		nd[i].t1 = lower_bound(lh + 1, lh + 1 + ltot, nd[i].t1) - lh,
    		nd[i].t2 = lower_bound(lh + 1, lh + 1 + ltot, nd[i].t2) - lh;
    }
    
  • 相关阅读:
    WP7 可以在XAML中使用的 缓存图片控件(适合静态)
    wp7蛋疼的90M内存限制,优化图片使用内存(4)[解决]
    Caliburn.Micro for wp7 学习笔记(2) : 响应 Butto事件
    Caliburn.Micro for wp7 学习笔记(3) : 响应 Butto事件原理
    Caliburn.Micro for wp7 学习笔记(1) : 建立 Caliburn.Micro 框架的 wp7 项目
    anthem.net 简单学习
    新公司研发能力低下,何去何从?
    C/C++指针和取地址操作
    利用bochs 调试(转)
    winform模式对话框和非模式对话框
  • 原文地址:https://www.cnblogs.com/JiaZP/p/13560032.html
Copyright © 2020-2023  润新知