题意

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

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

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

题解

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

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

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

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

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

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

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

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

总结

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

代码

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

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

#include <bits/stdc++.h>

#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<class Type> 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_shadow
freopen ("1124.in", "r", stdin);
freopen ("1124.out", "w", stdout);
#endif
} const int N = 1e6 + 1e3; int n, aim[N], deg[N], maxlive, minlive; bitset<N> dead, arrive; int main () { File(); n = read<int>();
For (i, 1, n) ++ deg[aim[i] = read<int>()]; queue<int> 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", n - maxlive, n - minlive); return 0;
}

BZOJ 1124: [POI2008]枪战Maf(构造 + 贪心)的更多相关文章

  1. BZOJ 1124: [POI2008]枪战Maf

    1124: [POI2008]枪战Maf Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 617  Solved: 236[Submit][Status ...

  2. bzoj 1124 [POI2008]枪战Maf 贪心

    [POI2008]枪战Maf Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 741  Solved: 295[Submit][Status][Disc ...

  3. 【刷题】BZOJ 1124 [POI2008]枪战Maf

    Description 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪.因此,对于不同的开枪顺序,最后死的人也不同. ...

  4. 【BZOJ】1124: [POI2008]枪战Maf

    题意 \(n(n < 1000000)\)个人,每个人\(i\)指向一个人\(p_i\),如果轮到\(i\)了且他没死,则他会将\(p_i\)打死.求一种顺序,问死的人最少和最多的数目. 分析 ...

  5. BZOJ1124 [POI2008]枪战Maf[贪心(证明未完成)+拓扑排序]

    吐槽:扣了几个小时,大致思路是有了,但是贪心的证明就是不会, 死磕了很长时间,不想想了,结果码代码又不会码.. 深深体会到自己码力很差,写很多行还没写对,最后别人代码全一二十行,要哭了 以下可能是个人 ...

  6. 【BZOJ1124】[POI2008]枪战Maf 贪心+思路题

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

  7. [POI2008]枪战Maf题解

    问题 C: [POI2008]枪战Maf 时间限制: 1 Sec  内存限制: 256 MB 题目描述 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺 ...

  8. [POI2008]枪战Maf

    [POI2008]枪战Maf 题目 有n个人,每个人手里有一把手枪.一开始所有人都选定一个人瞄准(有可能瞄准自己).然后他们按某个顺序开枪,且任意时刻只有一个人开枪.因此,对于不同的开枪顺序,最后死的 ...

  9. 【BZOJ 1124】[POI2008] 枪战Maf Tarjan+树dp

    #define int long long using namespace std; signed main(){ 这个题一看就是图论题,然后我们观察他的性质,因为一个图论题如果没有什么性质,就是真· ...

随机推荐

  1. CF1056E Check Transcription 字符串哈希

    传送门 暴力枚举\(0\)的长度,如果对应的\(1\)的长度也是一个整数就去check是否合法.check使用字符串哈希. 复杂度看起来是\(O(st)\)的,但是因为\(01\)两个数中数量较多的至 ...

  2. 使用HashSet<>去除重复元素的集合

    比如,某一个阵列中,有重复的元素,我们想去除重复的,保留一个.HashSet<T>含不重复项的无序列表,从MSDN网上了解到,这集合基于散列值,插入元素的操作非常快. 你可以写一个方法: ...

  3. 你要的fpga&数字前端笔面试题都在这儿了

    转自http://ninghechuan.com 你要的FPGA&数字前端笔面试题来了 FPGA&ASIC基本开发流程 题目:简述ASIC设计流程,并列举出各部分用到的工具. 勘误:C ...

  4. 在python中使用正则表达式(一)

    在python中通过内置的re库来使用正则表达式,它提供了所有正则表达式的功能. 一.写在前面:关于转义的问题 正则表达式中用“\”表示转义,而python中也用“\”表示转义,当遇到特殊字符需要转义 ...

  5. iOS开发简记(2):自定义tabbar

    tabbar是放在APP底部的控件.常见的APP都使用tabbar来进行功能分类的管理,比如微信.QQ等等. 小程需要一个特殊一点的tabbar,要求突显中间的那个按钮,让中间按钮特别显眼,从而引导用 ...

  6. Windows环境下实现Consul服务注册和服务发现

    1.首先从官方网站下载Consul,因为我们是使用的Windows系统,所以选择windows版本 https://www.consul.io/downloads.html 2.可以用开发者模式来启动 ...

  7. Nginx中防盗链(下载防盗链和图片防盗链)及图片访问地址操作记录

    日常运维工作中,设置防盗链的需求会经常碰到,这也是优化网站的一个必要措施.今天在此介绍Nginx中设置下载防盗链和图片防盗链的操作~ 一.Nginx中下载防盗链的操作记录对于一些站点上的下载操作,有很 ...

  8. Being a (amateurish) team:团队开发体会

    0x00 Being a (amateurish) team This is the process of changing hydrogen into breathable oxygen, and ...

  9. 第三个spring冲刺第10天

    进入最后阶段冲刺最后一天了,基本的需求已经完成了,最后的布局问题也解决了,我们的软件正式推出了.

  10. [转] Linux有问必答:如何修复“sshd error: could not load host key”

    编译自:http://ask.xmodulo.com/sshd-error-could-not-load-host-key.html作者: GOLinux 本文地址:https://linux.cn/ ...