P3210 [HNOI2010]取石头游戏

题目描述

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

与经典的取石子游戏相比,A公司举办的这次比赛的取石子游戏规则复杂了很多:

l 总共有N堆石子依次排成一行,第i堆石子有 ai个石子。

l 开始若干堆石子已被 A公司故意拿走。

l 然后两个玩家轮流来取石子,每次每个玩家可以取走一堆中的所有石子,但有一个限制条件:一个玩家若要取走一堆石子,则与这堆石子相邻的某堆石子已被取走(之前被某个玩家取走或开始被A公司故意拿走)。注意:第 1堆石子只与第 2堆石子相邻,第N堆石子只与第N-1堆石子相邻,其余的第 i堆石子与第i-1堆和第 i+1 堆石子相邻。

l 所有石子都被取走时,游戏结束。谁最后取得的总石子数最多,谁就获得了这场游戏的胜利。

作为这次比赛的参赛者之一,绝顶聪明的你,想知道对于任何一场比赛,如果先手者和后手者都使用最优的策略,最后先手者和后手者分别能够取得的总石子数分别是多少。

输入输出格式

输入格式:

第一行是一个正整数N,表示有多少堆石子。输入文件第二行是用空格隔开的N个非负整数a1, a2, ..., aN,其中ai表示第i堆石子有多少个石子,ai = 0表示第i堆石子开始被A公司故意拿走。输入的数据保证0<=ai<=100,000,000,并且至少有一个i使得ai = 0。30%的数据满足2<=N<=100,100%的数据满足2<=N<=1,000,000。

输出格式:

仅包含一行,为两个整数,分别表示都使用最优策略时,最后先手者和后手者各自能够取得的总石子数,并且两个整数间用一个空格隔开。

输入输出样例

输入样例#1: 复制

8

1 2 0 3 7 4 0 9

输出样例#1: 复制

17 9

样例解释:两个玩家都使用最优策略时取走石子的顺序依次为9, 2, 1, 4, 7, 3,因此先手

者取得9 + 1 + 7 = 17个石子,后手者取得2 + 4 + 3 = 9个石子。

题解

去年redbag寒假问我的题目。

我菜到今年才看懂题目。神仙题。

对于题目,给定几个双端队列和2个栈。

问怎么取最合适。

因为总值是确定的,我们只需要求出差值来。

最巧妙的地方,

在于我贪心一定是取当前可以取到的最大的,

若一个双端队列是单调的或者下凸的,不含上凸就可以了。

那么我们优先一个一个大的取就可以了。

为什么?

可以看一下我的学长举的例子

https://www.cnblogs.com/Y-E-T-I/p/8555129.html

如果可取元素都是递减的,比如

1 2 3 0 2 1 2 0 4 1

容易发现先手只要贪心地从能取的元素里面拣最大的取走即可。

这样不会给后手好情况。

由于每次一定可以取全场最大值,所以只要一次排序然后交替取值即可。

4 3 2 2 2 1 1 1

但是样例里就有上凸啊。

我们可以通过,\((a[i]<=a[i+1])\&\&(a[i+1]>=a[i+2])\) 来化为单调或者下凸。

我们把这三个点看成一个点,取这三个点并不影响后面的顺序。

一直化减下去,消掉上凸的情况,就只剩下栈的情况了。

对于栈我们这样取,当且仅当栈内每次取的比小于不能取的时,也就是单增时。我们判断当前石子的奇偶性。

为什么跟奇偶性相关?可以明确一点,栈内两个为一个周期一取,如果是奇数,那么两端最后取的一定是先手,反之后手。

举个例子,

一个栈有7个数,一个栈有4个数,第一个栈依次取进去,最后先手取到,且下一个开头为后手,所以4的也是先手取最后一个。

若是单调减的栈,直接和双端队列一样排序解决。

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<iostream>
#define ll long long
using namespace std;
const ll N=1e6+5;
ll l,r,ans;
ll n,a[N],sum,tot;
ll cnt,vis[N],s[N],top;
ll read(){
ll x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
} bool cmp(ll a,ll b){return a>b;} int main(){
n=read();
for(ll i=1;i<=n;i++){
a[++top]=read();sum+=a[top];
if(!a[top])vis[top]=1;
tot+=vis[top]^1;
while(top>=3&&(!vis[top])&&(!vis[top-1])&&(!vis[top-2])&&(a[top]<=a[top-1])&&(a[top-2]<=a[top-1])){
a[top-2]=a[top-2]+a[top]-a[top-1];top-=2;
}
}
for(l=1;(!vis[l])&&(!vis[l+1])&&a[l+1]<=a[l];l+=2)
ans+=(a[l]-a[l+1])*(tot&1?1:-1);
for(r=top;(!vis[r])&&(!vis[r-1])&&a[r]>=a[r-1];r-=2)
ans+=(a[r]-a[r-1])*(tot&1?1:-1);
for(ll i=l;i<=r;i++)
if(!vis[i])s[++cnt]=a[i];
sort(s+1,s+cnt+1,cmp);
for(ll i=1;i<=cnt;i++){
if(i&1)ans+=s[i];
else ans-=s[i];
}
cout<<(sum+ans)/2<<' '<<(sum-ans)/2<<endl;
return 0;
}

[luogu] P3210 [HNOI2010]取石头游戏(贪心)的更多相关文章

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

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

  2. 题解 洛谷 P3210 【[HNOI2010]取石头游戏】

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

  3. 【BZOJ2000】[HNOI2000]取石头游戏(贪心,博弈论)

    [BZOJ2000][HNOI2000]取石头游戏(贪心,博弈论) 题面 BZOJ 洛谷 题解 这题好神仙啊,窝不会QaQ. 假装一下只有三个元素\(a_{i-1},a_i,a_{i+1}\),并且满 ...

  4. [HNOI2010]STONE取石头游戏

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

  5. bzoj2000 [Hnoi2010]stone 取石头游戏

    Description A 公司正在举办一个智力双人游戏比赛----取石子游戏,游戏的获胜者将会获得 A 公司提供的丰厚奖金,因此吸引了来自全国各地的许多聪明的选手前来参加比赛. 与经典的取石子游戏相 ...

  6. BZOJ.2000.[HNOI2010]stone取石头游戏(博弈)

    BZOJ 洛谷 低估这道神题了_(:з」∠)_ MilkyWay好狠啊(小声) \(Description\) 有一些数字,被分成若干双端队列(从两边都可以取)和最多两个栈(只能从某一边一个一个取)的 ...

  7. 【Luogu】P2599取石子游戏(博弈论)

    题目链接 情况非常复杂,事实上题解我现在也没有完全理解 不过大致的意思就是 设两个数组lef[][],rig[][]表示对应区间左端加一堆数量为lef[][]的石子使得先手必败,rig同理 可以通过一 ...

  8. luogu 4411 [BJWC2010]取数游戏 约数+dp

    不大难的dp,暴力拆一下约数然后按照约数来统计即可. 注意:vector 很慢,所以一定特判一下,如果没有该数,就不要添加. Code: #include <bits/stdc++.h> ...

  9. [LuoguP1005]矩阵取数游戏 (DP+高精度)

    题面 传送门:https://www.luogu.org/problemnew/show/P1005 Solution 我们可以先考虑贪心 我们每一次都选左右两边尽可能小的数,方便大的放在后面 听起来 ...

随机推荐

  1. 执行目标文件引发的问题:syntax error: word unexpected (expe...

    今天不小心把一个目标文件当成了可执行文件放到开发板上进行执行,结果出现了这样一个问题:./hello_qt: line 1: syntax error: word unexpected (expect ...

  2. 《黑白团团队》第八次团队作业:Alpha冲刺 第一天

    项目 内容 作业课程地址 任课教师首页链接 作业要求 团队项目 填写团队名称 黑白团团队 填写具体目标 认真负责,完成项目 团队项目Github仓库地址链接. [Alpha] Scrum meetin ...

  3. 01springMVC入门

    1      MVC模式回顾 Spring MVC是一种基于MVC的Web应用框架. MVC是一种设计模式,MVC在b/s系统下的应用: 执行步骤: 发出请求,请求到MVC当中的C,C接收请求后并不能 ...

  4. hdu5319 Painter(模拟)

    题目链接:点击打开链接 题目大意:给一个矩形.有两把刷子,一把刷红色,一把刷蓝色,红色的方向是东南,蓝色的方向是西北,红色加蓝色等于绿色,如今已知这面墙当前的状态.求从白墙到这个状态最少刷了多少次. ...

  5. 关于ZipOupputStream添加压缩包常见问题

    其实园子压缩解压缩的方法很多,ZipOupputStream这个类的说明很多,我这边也是从网上找的代码,但是我在压缩的时候遇到了常见的两个问题,第一个就是压缩的时候读取压缩包报该压缩包已经在另一个进程 ...

  6. nginx报 File not found 错误

    原因可能非常多,但对于刚開始学习的人.大部分应该是/etc/nginx/conf.d/default.conf里面的php解析部分配置不正确. 解决的话就是把root定义.在server下加上,这样r ...

  7. bzoj3715: [PA2014]Lustra(乱搞)

    3715: [PA2014]Lustra 题目:传送门 题解: 随手一发水题x1 随便排序一下...小学生题??? 代码: #include<cstdio> #include<cst ...

  8. iOS开发中权限再度梳理

    前言 上篇文章iOS开发中的这些权限,你搞懂了吗?介绍了一些常用权限的获取和请求方法,知道这些方法的使用基本上可以搞定大部分应用的权限访问的需求.但是,这些方法并不全面,不能涵盖住所有权限访问的方法. ...

  9. SQL语句之transaction

    http://blog.csdn.net/xbc1213/article/details/50169935 案例: begin tran --定义一个存储错误新的变量 执行一条语句 set @sumE ...

  10. 一个基于React整套技术栈+Node.js的前端页面制作工具

    pagemaker是一个前端页面制作工具,方便产品,运营和视觉的同学迅速开发简单的前端页面,从而可以解放前端同学的工作量.此项目创意来自网易乐得内部项目nfop中的pagemaker项目.原来项目的前 ...