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


    Boring Card Game

    题目链接:luogu CF1427F

    题目大意

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

    思路

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

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

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


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

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

    于是就可以了!

    代码

    #include
    #include
    
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
  • 相关阅读:
    springcloud相关面试题
    字符串中的assert和strcat
    万恶的 eval() ?
    【排列组合】
    无锡设计培训:PLC控制的基本原则
    java对zip、rar、7z文件带密码解压实例
    AndroidTV开发12——大屏TV电视及盒子Apk远程安装说明文档
    JavaScript高阶笔记总结(Xmind格式):第一天
    AI 作画《NBA球星动漫头像》| 用stable diffusion生成
    hadoop生态圈面试精华之MapReduce(二)
  • 原文地址:https://blog.csdn.net/weixin_43346722/article/details/126273210