当前位置:网站首页>【luogu CF1427F】Boring Card Game(贪心)(性质)

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

2022-08-11 09:38:00 SSL_TJH

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;
}
原网站

版权声明
本文为[SSL_TJH]所创,转载请带上原文链接,感谢
https://blog.csdn.net/weixin_43346722/article/details/126273210