考虑到先手和后手都使用最优策略,所以可以像对抗搜索一样,设 \(val\) 为先手收益减去后手收益的值。那么先手想让 \(val\) 尽可能大,后手想让 \(val\) 尽可能小。

继续分析题目性质,发现取石子的过程可以转化为两端分别有一个栈,可以从栈顶取石子,中间有若干个双端队列,可以从其两端取石子。

如果取一个位置后,接下来的位置比刚才取的那个位置权值小,也就是从选择方向开始权值是递减的,每次决策肯定都是取当前局面权值最大的位置。如果不保证递减,就有可能取完一个位置后,使得一个权值更大的位置可以取,这时按最大值决策就有可能不是最优。

对于 \(a_{i-1},a_i,a_{i+1}\),若其满足 \(a_i \geqslant a_{i-1},a_i \geqslant a_{i+1}\),当一次决策选 \(a_{i-1}\) 最优时,先手选 \(a_{i-1}\),其后手一定会接着选 \(a_i\),然后先手会接着选 \(a_{i+1}\)。选 \(a_{i-1}\) 时,当前局面一定没有比 \(a_{i-1}\) 更好的选择,而 \(a_i\) 比 \(a_{i-1}\) 更优,所以后手一定选 \(a_i\),因为之前 \(a_{i-1}\) 是最优的选择,所以先手会接着选 \(a_{i+1}\)。因此把 \(a_{i-1},a_i,a_{i+1}\) 对 \(val\) 的贡献看作整体,将其合并为一个权值为 \(a_{i-1}+a_{i+1}-a_i\) 的石子。

合并完后所有的权值情况只存在递增,递减和下凹的情况了,这三个情况对于双端队列都是可以单调的从大到小选,对于从栈顶方向开始递减的栈的部分位置,也是可以单调的从大到小选,这些位置就可以直接排序后先后手一个一个选了。

而对于从栈顶方向开始递增的栈的部分位置,一定是最后才开始选的,因为这些决策一定是劣于其他决策,提前处理出其选择的结果,最后根据先后手的情况分配即可。

合并删除操作可以用链表来实现。

\(code:\)

#include<bits/stdc++.h>
#define maxn 2000010
using namespace std;
typedef long long ll;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
ll n,sum,val,s,L,R,tot;
ll l[maxn],r[maxn],v[maxn];
bool tag[maxn];
bool cmp(const ll &a,const ll &b)
{
return a>b;
}
int main()
{
read(n),r[0]=1,l[n+1]=n;
for(int i=1;i<=n;++i)
read(v[i]),sum+=v[i],l[i]=i-1,r[i]=i+1,tag[i]=(v[i]!=0);
for(int i=3;i<=n;i=r[i])
while(tag[l[l[i]]]&&tag[l[i]]&&tag[i]&&v[l[i]]>=v[l[l[i]]]&&v[l[i]]>=v[i])
v[i]=v[l[l[i]]]+v[i]-v[l[i]],r[l[l[l[i]]]]=i,l[i]=l[l[l[i]]];
L=r[0],R=l[n+1];
while(v[L]>=v[r[L]]&&tag[L]&&tag[r[L]]) s+=v[r[L]]-v[L],L=r[r[L]];
while(v[R]>=v[l[R]]&&tag[R]&&tag[l[R]]) s+=v[l[R]]-v[R],R=l[l[R]];
for(int i=L;i<=R;i=r[i])
if(tag[i])
v[++tot]=v[i];
sort(v+1,v+tot+1,cmp),v[++tot]=s;
for(int i=1;i<=tot;++i)
{
if(i&1) val+=v[i];
else val-=v[i];
}
printf("%lld %lld",(sum+val)/2,(sum-val)/2);
return 0;
}

题解 洛谷 P3210 【[HNOI2010]取石头游戏】的更多相关文章

  1. [luogu] P3210 [HNOI2010]取石头游戏(贪心)

    P3210 [HNOI2010]取石头游戏 题目描述 A 公司正在举办一个智力双人游戏比赛----取石子游戏,游戏的获胜者将会获得 A 公司提供的丰厚奖金,因此吸引了来自全国各地的许多聪明的选手前来参 ...

  2. luogu P3210 [HNOI2010]取石头游戏

    传送门 不会结论做个鬼系列 题意其实是在头尾(最多)两个栈以及中间一些双端队列依次取数,然后每个人都要最大化自己的价值 有一个结论,如果一段序列中,出现了三个相邻位置\(A,B,C\),满足\(A\l ...

  3. 【洛谷】P1247取火柴游戏

    题目链接:https://www.luogu.org/problemnew/show/P1247 题意:nim取石子的题意,多了一个判断先手赢的话,输出先手第一把怎么拿,以及拿完之后每堆还剩多少. 题 ...

  4. 洛谷 P1005 矩阵取数游戏

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...

  5. 【洛谷P1288】取数游戏II

    取数游戏II 题目链接 显然,由于一定有一个0,我们可以求出从初始点到0的链的长度 若有一条链长为奇数,则先手可以每次取完一条边上所有的数, 后手只能取另一条边的数,先手必胜: 反之若没有奇数链,后手 ...

  6. 洛谷P1005 矩阵取数游戏

    P1005 矩阵取数游戏 题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次 ...

  7. [NOIP2007] 提高组 洛谷P1005 矩阵取数游戏

    题目描述 帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的n*m的矩阵,矩阵中的每个元素aij均为非负整数.游戏规则如下: 1.每次取数时须从每行各取走一个元素,共n个.m次后取完矩阵所有元素: 2. ...

  8. 洛谷 P2252 [SHOI2002]取石子游戏|【模板】威佐夫博弈

    链接: P2252 [SHOI2002]取石子游戏|[模板]威佐夫博弈 前言: 第一眼大水题,第二眼努力思考,第 N 眼我是大水逼. 题意: 不看题目标题都应该能看出来是取石子类的博弈论. 有两堆石子 ...

  9. 题解 洛谷 P3185 【[HNOI2007]分裂游戏】

    首先可以发现,当所有巧克力豆在最后一个瓶子中时,就无法再操作了,此时为必败状态. 注意到,对于每个瓶子里的巧克力豆,是可以在模\(2\)的意义下去考虑的,因为后手可以模仿先手的操作,所以就将巧克力豆个 ...

随机推荐

  1. Nginx负载均衡的详细配置 + Keepalived使用

    1,话不多说, 这里我们来说下很重要的负载均衡, 那么什么是负载均衡呢? 由于目前现有网络的各个核心部分随着业务量的提高,访问量和数据流量的快速增长,其处理能力和计算强度也相应地增大,使得单一的服务器 ...

  2. vueX基础知识点笔记

    vuex是专门用来管理vue.js应用程序中状态的一个插件.他的作用是将应用中的所有状态都放在一起, 集中式来管理.需要声明的是,这里所说的状态指的是vue组件中data里面的属性.简单的来说, 它就 ...

  3. 使用nginx配置域名及禁止直接通过IP访问网站

    前段时间刚搭建好个人网站,一直没有关注一个问题,那就是IP地址也可以访问我的网站,今天就专门研究了一下nginx配置问题,争取把这个问题研究透彻. 1. nginx配置域名及禁止直接通过IP访问 先来 ...

  4. ubuntu无法安装vim、tree等解决办法

    rm /etc/apt/sources.list.d/* 删除该目录下所有文件

  5. day19__生成器,迭代器

    一.列表解析 l1 = ['鸡蛋%s' % i for i in range(10) if i > 5] print(l1) # ['鸡蛋6', '鸡蛋7', '鸡蛋8', '鸡蛋9'] 这种方 ...

  6. git和github入门指南(5)

    5.github上的标签 5.1.标签的作用 给当前版本打一个标签,在github上就会形成一个releases版本 点击进去后,用户就可以下载对应版本的源代码 5.2.在本地git工具上创建标签,同 ...

  7. Zuul请求超时

    最近在弄springcloud的时候发现在发送短信的时候zuul总是报错,错误信息如下 com.netflix.zuul.exception.ZuulException: at org.springf ...

  8. Docker(六)容器数据卷

    容器数据卷 docker的理念回顾 将应用和环境打包成一个镜像 需求:数据可以持久化和同步 使用数据卷 指定路径挂载 docker run -it -v 主机目录:容器内目录 # 测试 [root@h ...

  9. bitbucket的简单使用

    1.如果你已经把项目建好的话,那么提交上去这样:没有构建本地仓库的话,那先打包本地,到你的项目路径上去后git initgit remote add origin https://linjiayu@b ...

  10. java语言进阶(五)_异常

    第一章 异常 1.1 异常概念 异常 :指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止. 在Java等面向对象的编程语言中,异常本身是一个类,产生异常就是创建异常对象并抛出了 ...