首页 > 其他分享 >题解:【ARC112C】 DFS Game

题解:【ARC112C】 DFS Game

时间:2023-03-19 09:11:45浏览次数:47  
标签:硬币 ARC112C 题解 int Game siz now 节点 dp

题目链接

题目里面的注意点还是很多的,如果读错了题整个思路可能会一点都不对。首先是移动和选取硬币的操作是分开的,所以你移动到了一个有硬币的节点,将是你的对手获得硬币。然后移动和拿取都是单次操作的,进行后就换人了。

如果要使总答案最优,那每个节点的决策都要最优。选择了一个节点就要决策完他的整个子树。因此考虑树形DP,我们用儿子来推父亲,当决策一个节点的时候,他的子节点信息我们都已经知道。

设 \(g_i\) 表示点 \(i\) 的子树大小,\(f_i\) 表示在当前节点先手能够得到的最多硬币,那么后手能够得到的最多硬币我们记为 \(h_i = g_i - f_i\)。

模拟几个小数据,假设一个人选择了当前的一个子节点 \(i\) 进入,能够发现当 \(g_i\) 为奇数时,回到 \(i\) 的父亲后变成他的对手进行子节点的选择;当 \(g_i\) 为偶数时,回到 \(i\) 的父亲后仍为他自己选择下一个进入的子节点。

所以一个节点如果有奇数个 \(g\) 为奇数的子节点,最后会交换决策权;偶数个 \(g\) 为奇数的子节点,决策权不变。

我们对子节点的状态分类讨论,均假设为先手拿取了该节点 \(i\) 的硬币,接下来该由后手决策进入哪个子节点 \(j \in son_i\):

  1. \(g_j\) 为偶数且 \(f_j < h_j\),那么对于后手来说这个节点肯定是有利的,因为他能拿得多,还能回来后继续操控局面,所以只要有这类节点,后手必定会选,此类节点的转移方程为 \(f_i = f_i + f_j\)。
  2. \(g_j\) 为偶数且 \(f_j \le h_j\),那么对于后手来说这个节点不是亏的就是没有贡献,所以会尽量避免选这类节点,此类节点的转移为 \(f_i = f_i + h_j\)。
  3. \(g_j\) 为奇数,注意到选择了这类节点后会交换决策权,所以后手会尽量选择优秀的节点——能让他比对手拿得更多的节点,即 \(h_i - f_i\) 尽可能大的节点。

所以整个游戏的流程至此我们能够确定下来了:先拿第一类节点,然后拿第三类节点。判断一下第三类节点总数的奇偶性,看选完第三类节点后会不会交换决策权,从而看第二类节点的贡献到底是给先手还是后手。

整个遍历流程是 \(\mathcal O(n)\) 的复杂度,由于需要我们决策具体哪个第三类节点更优,这里选择使用优先队列,所以总复杂度为 \(\mathcal O(n \log n)\)。

#include<bits/stdc++.h>
#define int long long
#define mp make_pair
using namespace std;

inline int read()
{
	int s=0,w=1;
	char c=getchar();
	while(!isdigit(c)) {if(c=='-') w=-1; c=getchar();}
	while(isdigit(c)) s=(s<<1)+(s<<3)+(c^48),c=getchar();
	return s*w;
}

bool Mbe;

namespace LgxTpre
{
	static const int MAX=100010;
	static const int INF=2007070707;
	static const int mod=998244353;
	
	int n,x;
	
	struct edge
	{
		int nex,to;
	}e[MAX<<1];
	int head[MAX],cnt;
	inline void add(int x,int y)
	{
		e[++cnt].nex=head[x],head[x]=cnt,e[cnt].to=y;
		return;
	}

	#define to e[i].to
	int siz[MAX],dp[MAX];
	priority_queue<pair<int,int> > q;
	void dfs(int now)
	{
		int tot=0,con=0;
		siz[now]=1;
		for(int i=head[now];i;i=e[i].nex) 
			dfs(to),siz[now]+=siz[to],tot^=siz[to]&1;
		dp[now]=1;
		for(int i=head[now];i;i=e[i].nex)
		{
			if(siz[to]&1)
				q.push(mp(siz[to]-2*dp[to],dp[to]));
			else 
			{
				if(dp[to]<siz[to]-dp[to]||(dp[to]>=siz[to]-dp[to]&&(!tot))) 
					dp[now]+=dp[to]; 
				else
					dp[now]+=siz[to]-dp[to];
			}
		}
		while(!q.empty())
		{
			++con;
			auto it=q.top(); q.pop();
			if(con&1) dp[now]+=it.second;
			else dp[now]+=it.first+it.second;
		}
		return;
	} 
	#undef to
	
	inline void mian()
	{
		n=read();
		for(int i=2;i<=n;++i)
			x=read(),add(x,i);
		dfs(1);
		printf("%lld",dp[1]);
		return;
	}
}

bool Med;

signed main()
{
//	fprintf(stderr,"%.3lf MB\n",(&Mbe-&Med)/1048576.0);
	LgxTpre::mian();
	return (0-0);
}

标签:硬币,ARC112C,题解,int,Game,siz,now,节点,dp
From: https://www.cnblogs.com/LittleTwoawa/p/17232451.html

相关文章

  • .net6 docker部署,以及问题解决(附Dokerfile)
    搭建仓库,发布配置docker搭建私有仓库参考上文,搭建好私有仓库,成功访问http://127.0.0.1:5000/v2/_catalog之后:在VS右键=>添加=>Docker支持=>选择Linux,即可自动......
  • 蓝桥楼赛第23期-工作文件整理归类 题解
    题目描述实小楼同学平常的工作比较繁杂,经常需要处理各类文档,几天时间桌面上就累积了一堆不同类型和名称的文档,显得十分杂乱。实小楼想通过Python编写一个脚本,能够自动归......
  • Tree Depth P 题解
    TreeDepth题意\(~~~~\)对一个排列建立小根笛卡尔树,定义第\(i\)个位置的权值为其在笛卡尔树上的深度。求对于所有恰好有\(k\)个逆序对的排列,每个位置的权值和对一......
  • AGC012 题解
    chrislgjeztorAmledzaprofovelmizerdoscarmammeidhaalzengharkawymaynoxialgjeztorRupieillavasphotreywzidha[AGC012A]AtCoderGroupContest普及题......
  • [ABC245E] Wrapping Chocolate题解
    听说没人写,那就来一发。这种偏序问题大概率是要排个序的。将盒子和巧克力视为一个东西,\(c\)视为\(a\),\(d\)视为\(b\),放在一起以\(a\)为第一关键字,\(b\)为第二关键......
  • CF1442F Differentiating Games
    CF1442FDifferentiatingGames传送门CF1442FDifferentiatingGames题目大意给你一个DAG,\(n(n\le1000)\)个点,\(m(m\le10^5)\)条边。一次游戏为:两人轮流操作,每......
  • java.sql.SQLSyntaxErrorException: Table 'test.user' doesn't exist报错问题解决
    以下内容仅供自己学习使用,侵权必删在使用mubatis-plus的时候报错了以下内容java.sql.SQLSyntaxErrorException:Table'test.user'doesn'texist解决方法:2.1在......
  • CF1804F Approximate Diameter 题解
    前言在学校机房被学长推荐了这道题,听完正解后惊为天人...简化版题面给定一张无向连通图,定义直径\(d=\max(dis(i,j))\quad(i,j\inN)\),其中\(dis(i,j)\)指的是\(......
  • 【题解】ABC293E Sol
    题目大意给定整数\(A,X,M\),求\(\sum\limits^{X-1}_{i=0}A^i\)对\(M\)取模的值。数据范围:\(1\leA,M\le10^9\),\(1\leX\le10^{12}\)。题目分析直接算显然......
  • h5中audio无法播放问题解决
    H5页面中添加audio标签,通过调用play()方法进行播放音频,电脑可以正常听到音效,微信中打开没有声音。<audioid="audio"ref="audio"class="sound"><sourcesrc="@/st......