【luogu CF1427F】Boring Card Game(贪心)(性质)

Boring Card Game

题目链接:luogu CF1427F

题目大意

给你 6n 张牌循序排列,两个人轮流每次取连续的三张。
然后给你第一个人要的 3n 张牌,保证有方法能取到,要你输出方案。
(不是博弈,两人可以视为合作)

思路

首先因为一定有解,考虑这么一个贪心:
从左往右维护一个栈,每次有三张一样的就取,那如果不考虑顺序一定可以。
而且因为你思考一下会发现这是唯一的方案,而且有解,所以我们考虑给顺序。

然后发现它会变成一个类似括号序列的东西(你可以给最左边的和最右边的分别给左右括号),那么就是一个括号它要被删掉的话它里面一定不能有东西。
那就是括号数要删完儿子再删他,每个颜色轮流删,构造方法。

考虑找性质,发现相邻层颜色一定不同。
于是考虑一些做法,发现并没有什么搞法,考虑乱搞并证明(bushi


如果乱选行吗(
不如试试:
对于先手要选的点,我们不难证明如果有解一定会有在叶子的位置的。
首先如果有解那最后一个(也就是存在一个根)是给后手的。
然后我们考虑反证,如果不在叶子,那由于颜色交替,一条边两个点肯定不同颜色,那我们就可以考虑每个后手的点跟它的父亲匹配,但是这样根的后手点就没得匹配,就矛盾了。
(可以直接匹配是因为还有一个性质是这个时候两种点的个数相同)

那后手我们只要不删掉最后一个它能删的根即可(当然只剩一个就无所谓啦)

于是就可以了!

代码

#include<queue> #include<cstdio> using namespace std; const int N = 205; int n, x, sta[N * 6], pla[N * 6], rtnum, sons[N * 2], dy[N * 6], tot, fa[N * 6]; bool in[N * 6], col[N * 2], rt[N * 2]; vector <int> dys[N * 2]; int main() { scanf("%d", &n); for (int i = 1; i <= 6 * n; i++) in[i] = 1; for (int i = 1; i <= 3 * n; i++) { scanf("%d", &x); in[x] = 0; } for (int i = 1; i <= 6 * n; i++) { sta[++sta[0]] = i; if (sta[0] == 1 || in[sta[sta[0]]] != in[sta[sta[0] - 1]]) pla[i] = ++tot, col[tot] = in[sta[sta[0]]], dy[i] = tot; else if (sta[0] >= 3 && in[sta[sta[0]]] == in[sta[sta[0] - 1]] && in[sta[sta[0]]] == in[sta[sta[0] - 2]]) pla[i] = -pla[sta[sta[0] - 2]], dy[i] = dy[sta[sta[0] - 1]], sta[0] -= 3; else dy[i] = dy[sta[sta[0] - 1]]; dys[dy[i]].push_back(i); } // if (sta[0]) while (1); for (int i = 1; i <= 6 * n; i++) if (pla[i]) { if (pla[i] > 0) { if (!sta[0]) rtnum += in[i], rt[pla[i]] = 1; else fa[pla[i]] = pla[sta[sta[0]]], sons[fa[pla[i]]]++; sta[++sta[0]] = i; } else { if (!sta[0]) while (1); sta[0]--; } } // if (sta[0]) while (1); queue <int> q0, q1; while (!q0.empty()) q0.pop(); while (!q1.empty()) q1.pop(); for (int i = 1; i <= tot; i++) if (!sons[i]) { if (col[i]) q1.push(i); else q0.push(i); } while (!q0.empty()) { int now = q0.front(); q0.pop(); printf("%d %d %d\n", dys[now][0], dys[now][1], dys[now][2]); sons[fa[now]]--; if (!sons[fa[now]]) {if (col[fa[now]]) q1.push(fa[now]); else q0.push(fa[now]);} // if (q1.empty()) while(1); now = q1.front(); q1.pop(); if (!(q1.empty() || rtnum > 1 || !rt[now])) { int tmp = now; now = q1.front(); q1.pop(); q1.push(tmp); } printf("%d %d %d\n", dys[now][0], dys[now][1], dys[now][2]); sons[fa[now]]--; if (!sons[fa[now]]) {if (col[fa[now]]) q1.push(fa[now]); else q0.push(fa[now]);} if (rt[now]) rtnum--; } return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/luogu_CF1427F.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(40)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示