首页 > BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)

BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)

题意

(n) 个人,每个人手里有一把手枪。一开始所有人都选定一个人瞄准(有可能瞄准自己)。然后他们按某个顺序开枪,且任意时刻只有一个人开枪。

因此,对于不同的开枪顺序,最后死的人也不同。

问最后死的人数最小值以及最大值。 ((1 le n le 10^6))

题解

不难发现是一道思博构造题。

首先考虑下最大值,我们只需要把这张图分三种情况讨论:

  1. 单个自环,贡献为 (1)
  2. 一个大于 (1) 的环,贡献为 (len - 1)
  3. 一个基环树,贡献为 (size - num_{leaf})

对于最小值的话,我们可以不断模拟。

具体来说就是一开始把入度为 (0) 的人加入,这些人是活着的,然后他们瞄准的人就是必死的。

每次考虑连续三个点就行了,他们的顺序就是 活 ( o)( o) 活 的。(其实第三个人不一定活的)

然后我们对于第三个点的入度就会 (-1) ,如果为 (0) 我们加进队列继续操作。(这就意味着,它在其中任何一次死了。我们都不会加进去)

然后这样不断操作,最后只会留下环,不难发现环上至少死 (displaystyle lceil frac{len}{2} ceil) 个人,这样就可以做完了qwq

总结

构造题认真想想还是想的出来的,但是需要大胆猜想小心求证才行qwq

代码

这道题实现起来其实有一些巧妙之处,建议读者仔细阅读。(参考了一下 ACist大佬的博客 )

我这个代码加上流输入,就可以取得 BZOJ 速度 rank1 的好成绩qwq

#include #define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << x << endl
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)using namespace std;inline bool chkmin(int &a, int b) {return b < a ? a = b, 1 : 0;}
inline bool chkmax(int &a, int b) {return b > a ? a = b, 1 : 0;}namespace pb_ds
{   namespace io{const int MaxBuff = 1 << 16;const int Output = 1 << 22;char B[MaxBuff], *S = B, *T = B;#define getc() ((S == T) && (T = (S = B) + fread(B, 1, MaxBuff, stdin), S == T) ? 0 : *S++)char Out[Output], *iter = Out;inline void flush(){fwrite(Out, 1, iter - Out, stdout);iter = Out;}}template inline Type read(){using namespace io;register char ch; register Type ans = 0; register bool neg = 0;while(ch = getc(), (ch < '0' || ch > '9') && ch != '-')     ;ch == '-' ? neg = 1 : ans = ch - '0';while(ch = getc(), '0' <= ch && ch <= '9') ans = ans * 10 + ch - '0';return neg ? -ans : ans;}
}using namespace pb_ds;void File() {
#ifdef zjp_shadowfreopen ("1124.in", "r", stdin);freopen ("1124.out", "w", stdout);
#endif
}const int N = 1e6 + 1e3;int n, aim[N], deg[N], maxlive, minlive; bitset dead, arrive;int main () {File();n = read();For (i, 1, n) ++ deg[aim[i] = read()];queue Q;For (i, 1, n) if (!deg[i]) Q.push(i), ++ minlive;while (!Q.empty()) {int u = aim[Q.front()], v = aim[u]; Q.pop();++ maxlive; if (dead[u]) continue ;dead[u] = true; arrive[v] = true;if (!(-- deg[v])) Q.push(v);}For (i, 1, n) if (deg[i] && !dead[i]) {int len = 0; bool flag = false;for (register int u = i; !dead[u]; u = aim[u]) dead[u] = true, ++ len, flag |= arrive[u];if (!flag && len > 1) ++ minlive;maxlive += len / 2;}printf ("%d %d
", n - maxlive, n - minlive);return 0;
}

转载于:https://www.cnblogs.com/zjp-shadow/p/9477479.html

更多相关:

  •         Apache POI是一个开源的利用Java读写Excel,WORD等微软OLE2组件文档的项目。        我的需求是对Excel的数据进行导入或将数据以Excel的形式导出。先上简单的测试代码:package com.xing.studyTest.poi;import java.io.FileInputSt...

  • 要取得[a,b)的随机整数,使用(rand() % (b-a))+ a; 要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a; 要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1; 通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。 要取得a到b之间的...

  • 利用本征图像分解(Intrinsic Image Decomposition)算法,将图像分解为shading(illumination) image 和 reflectance(albedo) image,计算图像的reflectance image。 Reflectance Image 是指在变化的光照条件下能够维持不变的图像部分...

  • 题目:面试题39. 数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输出: 2 限制: 1 <= 数组长度 <= 50000 解题: cl...

  • 题目:二叉搜索树的后序遍历序列 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。 参考以下这颗二叉搜索树:      5     /    2   6   /  1   3示例 1: 输入: [1,6,3,2,5] 输出...

  • $dp$。 这道题最关键的是这句话: 跳出思维局限大胆设状态,设$f_{x, i, j}$表示从$x$到根要经过$i$条公路,$j$条铁路的代价,那么对于一个叶子结点,有$f_{x, i, j} = c_x * (a_x + i) * (b_x + j)$,对于内部结点,有转移:   $f_{x, i, j} = min(f_{lso...

  • 合作者:201631062327,201631062128码云地址:https://gitee.com/LIUJIA6/WordCount3 一:项目说明 本次项目是在上次作业WorldCount的基础上,利用结对编程的思想,完成对WorldCount项目的功能扩展 -s 递归处理目录下符合条件的文件。(实现)-a 返回更复杂的数据(...

  • Description 魔咒串由许多魔咒字符组成,魔咒字符可以用数字表示。例如可以将魔咒字符 1、2 拼凑起来形成一个魔咒串 [1,2]。 一个魔咒串 S 的非空字串被称为魔咒串 S 的生成魔咒。 例如 S=[1,2,1] 时,它的生成魔咒有 [1]、[2]、[1,2]、[2,1]、[1,2,1] 五种。S=[1,1,1] 时,它的生...

  •   【题目链接】 http://acm.hdu.edu.cn/showproblem.php?pid=5972   【题目大意】   给出一个字符串,找出其中所有的符合特定模式的子串位置,符合特定模式是指,该子串的长度为n,并且第i个字符需要在给定的字符集合Si中    【题解】   利用ShiftAnd匹配算法。   bt[i]表示...

  • 首先我们可以发现如果错过了一个加油站,而继续往前走的时候没有油了,可以再假装之前经过加油站的时候加过油 于是我们维护一个大根堆,表示错过的加油站是哪些,每当没有油的时候从堆顶取出最大值加上去即可   1 /**************************************************************...

  • 下面是以道友问的问题,这里简单做分析,仅供交流学习用,有什么不对之处还请各位大虾指正。鄙人邮箱为:[email protected]. 欢迎交流!!1: 最主要的就是路由问题。我用06协议栈自带的例子程序sampleapp修改了一下,另协调器以网络地址的形式向终端发送数据,中间加入路由转发数据。拿 到室外试验了一下,结果路由根本不起...

  • 题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=2819 题意:给一张n*n的01矩阵,可以任意交换其中的行或者列,问是否可以交换出来一个对角线上都是1的矩阵。 按行列号建图,如果(i,j)为1的话,则i和j就有一条边。匹配出的结果可以认为如何交换使得行列相等,输出结果要注意不...

  • U-Boot 实验指导书 一、获得U-Boot 源码 我们的光盘中提供了直接从U-Boot的官方网站下载的源代码,版本是1.3.2,放在src目录下。将u-boot-1.3.2.tar.bz2拷贝了工作目录下,解压源码包: [root@localhost root]# mkdir 2410-s [root@localhost roo...

  • USB设备枚举过程中使用到的常量定义如下: /*-------------------------------------------------------------------------  * Standard Chapter 9 definition  *----------------------------------...