【题解】P3210 [HNOI2010] 取石头游戏

news/2024/10/12 4:31:27

\(\large\mathfrak{1st.\ Preamble|}\) 前言

题目传送门:P3210 [HNOI2010] 取石头游戏)

主要是参考楼下大佬的题解,对于其中没讲到或比较难懂的地方进行讲解,以及配上了图。

\(\large\mathfrak{2nd.\ Solution|}\) 题解

楼下大佬的比喻十分形象生动地描绘了俩人去石头的过程:

取石子的过程可以转化为两端分别有一个栈,可以从栈顶取石子,中间有若干个双端队列,可以从其两端取石子。

我们可以根据俩人取石子的过程推算出先手积分减去后手积分的差值 \(dif\),然后根据总和就能求出最终俩人的积分。先手肯定希望 \(dif\) 尽可能大,后手肯定希望 \(dif\) 尽可能小。

Q:为什么是算差值而不是直接算积分?

A:因为差值好算呗!等会你就知道了。

为了方便计算,我们肯定希望每次的全局最大权值的位置都是可以直接取的。接下来我们分两个部分讨论这俩人取石子的过程。

注:接下来的递减、递增均指非严格递减和递增。

中间部分(双端队列)

对于每个中间区块(双端队列)中,权值递增、递减和下凹的情况都很好解决,如下图箭头所示,从其中一端或两端开始取就行。

然后我们来看看上凸该如何解决。

我们先来考虑最简单的三个位置的上凸情况:若存在 \(a_{i-1}\le a_i\) 并且 \(a_i\ge a_{i+1}\),若当前最优选择为 \(a_{i-1}\),则先手会选择 \(a_{i-1}\),接着后手会选择 \(a_i\),然后先手会选择 \(a_{i+1}\),最终 \(dif\) 会增加(或减少)\(a_{i-1}-a_i+a_{i+1}\),于是我们就可以把 \(a_{i-1}, a_i, 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\)\(a_{i+1}\) 打包成一个权值为 \(a_{i+1}-a_i\) 的位置。

右边部分同理。

实现方法

全部打包完后,接下来每次的全局最大值必定可以直接取到,所以我们可以直接将所有位置按权值从大到小排序,然后从大到小取即可。

\(\large\mathfrak{3rd.\ Code|}\) 代码

代码中过于简单的细节就不标注了。敢做黑题的相信一定能看懂。

#include <bits/stdc++.h>
#define ll long long
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define FILE(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout);
#define pii pair<int,int>
#define pll pair<long long,long long>
// #define Clock
using namespace std;
const ll N=2e6+10;
ll n,a[N],sum,l[N],r[N],L,R,p[N],cnt,s,ans;
bool book[N];
inline bool cmp(ll a,ll b){return a>b;}
int main(){#ifdef Clockclock_t Start_Time=clock();#endif// ios::sync_with_stdio(false);// cin.tie(0),cout.tie(0);// FILE("xxx");cin>>n; r[0]=1,l[n+1]=n;for(ll i=1;i<=n;i++){cin>>a[i];sum+=a[i],book[i]=a[i];l[i]=i-1,r[i]=i+1;}for(ll i=3;i<=n;i=r[i]){ll x=l[l[i]],y=l[i],z=i;while(book[x]&&book[y]&&book[z]&&a[y]>a[x]&&a[y]>a[z]){a[i]=a[x]+a[z]-a[y],r[l[x]]=i,l[i]=l[x];x=l[l[i]],y=l[i],z=i;}}L=r[0],R=l[n+1];while(a[L]>=a[r[L]]&&book[L]&&book[r[L]])s-=a[L]-a[r[L]],L=r[r[L]];while(a[R]>=a[l[R]]&&book[R]&&book[l[R]])s-=a[R]-a[l[R]],R=l[l[R]];for(ll i=L;i<=R;i=r[i])if(book[i])p[++cnt]=a[i];sort(p+1,p+cnt+1,cmp);p[++cnt]=s;for(ll i=1;i<=cnt;i++)ans+=(i%2?p[i]:-p[i]);cout<<(sum+ans)/2<<' '<<(sum-ans)/2;#ifdef Clockcout<<"\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\nRuntime: "<<clock()-Start_Time<<" ms\n";system("pause");#endifreturn 0;
}

\(\large\mathfrak{4th.\ Postscript|}\) 后记

第一天写的时候没过,那时还是紫题,并且不能写题解。第二天过完后发现变成了黑题,而且还可以写题解!于是遍欣喜若狂地写下了这篇题解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/53421.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

实现定制化 AutoGPT 实战

简介 在前面的学习过程中,已经了解到了 AutoGPT 基本的环境安装操作。接下来就可以基于 AutoGPT 完成一些有趣的任务。通过 AutoGPT 实现我们的需求 环境准备 在正式使用 AutoGPT 之前,确认以下环境没有任何问题:稳定的上网环境。 配置好的 AutoGPT 环境。 可以使用的 token…

osg与IFC(BIM)

IFC(BIM) BIM管理中使用的模型格式:IFC IFC简介 IFC模型体系结构由四个层次构成, 从下到上依次是 资源层(Resource Layer)、核心层(Core Layer)、交互层(Interoperability Layer)、领域层(Domain Layer)。 每层中都包含一系列的信息描述模块,并且遵守一个规则:每个层次只能…

面试官:Leader崩溃Follower不够新怎么办?

这是一道非常经典的 Kafka 问题,是关于 Leader 在“异常”情况下的选举问题。 背景 我们知道 Kafka 中的 Partition(分区)是存储消息的最终介质,但 Partition 又有两种分类:Leader Partition:主分区,负责数据写入和读取。 Follower Partition:副本分区,用于数据备份和…

线性规划单纯形求解理论

线性规划(Linear Programming, LP)是优化理论中用于在给定约束条件下最大化或最小化线性目标函数的一种数学方法。线性规划的最优解总是出现在可行域的顶点上,这是因为目标函数在可行域内的变化是线性的,因此在顶点处函数的值可能达到极值(最大或最小)。求解线性规划问题…

如何考取PostgreSQL认证证书?

PostgreSQL数据库炙手可热,国内知名的腾讯云TDSQL、阿里云PolarDB都有PostgreSQL版本的产品,还有人大金仓、华为opengauss、翰高数据库等都跟PostgreSQL有关系,所以考一个PostgreSQL认证非常有必要。要获得PostgreSQL认证,可以从以下几个方面着手: 一、了解PostgreSQL认证…

AI agent里的长期记忆和短期记忆

AI Agent 是时下热门的一个方向,在 OpenAI 应用研究主管 LilianWeng 写的万字长文中[1],她提出 Agent = LLM+ 记忆 + 规划技能 + 工具使用。图1 Overview of a LLM-powered autonomous agent system组件二:记忆我们可以将上下文学习(context)看成是利用模型的短期记忆(也…

Yolov5模型训练+转ncnn模型

配置YOLOv5依赖 打开yolov5开源地址:https://github.com/ultralytics/yolov5 可根据自身要求下载对应版本(无要求可跳过): 下载:下载完成安装依赖包: 如需使用显卡进行训练需按照显卡版本安装部分依赖包:这两个包注掉,然后根据显卡版本安装依赖 在cmd获取显卡版本:nvi…

windows更新在哪里删除,教你关闭windows更新

电脑自动更新的彻底关闭方法可以根据不同的Windows系统版本(如Windows 10、Windows 11等)和用户的具体需求来选择。以下是一些常用的方法: 一、 使用系统设置关闭自动更新 步骤: 1.点击开始菜单,在搜索栏中输入“设置”,并打开设置窗口。 2.在设置窗口中,找到“更新和安…