题面传送门

题意:

  • 有 \(n\) 条蛇,每条蛇有个实力 \(a_i\)
  • 我们称编号为 \(x\) 的蛇比编号为 \(y\) 的蛇强,当且仅当 \(a_x>a_y\) 或 \(a_x=a_y\) 且 \(x>y\)。
  • 每次实力最强的蛇可以选择吃掉实力最弱的蛇或者不吃,如果实力最强的蛇选择吃,那么它的实力会减去实力最弱的蛇的实力,实力最弱的蛇将消失。
  • 假设每条蛇都会选择最优策略(在保证自己不被吃的条件下吃掉尽可能多的别的蛇),问最后会剩下多少条蛇。
  • \(\sum n\le 10^7\)

薅洛谷题解 ing

首先我们来挖掘一些性质。可以发现,如果一条蛇吃完最弱的蛇之后不是最弱的蛇,那么它一定会选择吃。因为如果最强的蛇吃完最弱的蛇之后还是最强的蛇,那它不吃白不吃。否则,下一步最强的蛇的实力肯定是弱于原来最强的蛇的实力的,并且由于这条蛇吃完之后不是最弱的蛇,最弱的蛇的实力也强于原来最弱的蛇的实力,也就是说,下一步最强的蛇吃完最弱的蛇之后,肯定比当前最强的蛇吃完最弱的蛇之后的实力更菜,也就是说,如果下一步最强的蛇死了,那它死的时间肯定比当前这条蛇死的时间早,而下一步最强的蛇肯定会选择保住自己,因此下一步最强的蛇一定不会死,故就算这一步最强的蛇吃了最弱的蛇,它也不会死,因此它肯定会选择吃。

那么如果一条蛇吃了最弱的蛇之后变成了最弱的蛇之后怎么办呢?显然,如果一条蛇吃了最弱的蛇之后变成了最弱的蛇,而下一步最强的蛇吃了最弱的蛇之后不是最弱的蛇,或者下一步只剩两条蛇,那它肯定不会吃,因为如果它吃了最弱的蛇,那么下一步最强蛇可以安心吃掉最弱的蛇,它也就挂掉了。

我们再往前回溯一格,如果一条蛇吃了最弱的蛇后,下一步最强的蛇满足之前所述的状态,那么这条蛇会选择吃掉最弱的蛇,因为下一步最强蛇不敢吃最弱的蛇,否则它就会死。因此这一步最强的蛇可以放心大胆地吃,而下一步的蛇又不敢吃,因此这种情况总蛇数会少一。

如果再往前回溯一格那也可以得到类似的结论,如果最强蛇吃完最弱蛇之后回到了上一步所说的状态,那它又不敢吃了,因为吃了之后下一步最强蛇可以安心吃最弱蛇。

我们可以发现,出现最强蛇吃了最弱蛇的情况之后,答案会不会减少一,取决于当前局面到最强蛇能够安心吃掉最弱蛇经过的轮数的奇偶性,如果不算“第一次出现最强蛇吃了最弱蛇变成最弱蛇”这一轮,算上“最强蛇能够安心吃掉最弱蛇”这一轮之后,轮数是偶数,那么答案会减少一。因此我们考虑将整个过程分为两个部分:

  • 第一部分:最强蛇吃完最弱蛇之后都不是最弱蛇,放心大胆吃,答案减一
  • 第二部分:出现某个最强蛇吃完最弱蛇之后是最弱蛇:重复上面的过程直到出现一条最强蛇可以放心大胆地吃掉最弱蛇,根据第二部分持续的轮数判断答案是否减一。

直接 set 维护大概可以拿到 70 分的好成绩。考虑优化。我们建立两个 deque,分别称作 \(q_1,q_2\),维护现在没有吃过别的蛇,和现在已经吃过别的蛇的蛇的实力,实力从队首到队尾依次递减,然后考虑如下过程:

  • 第一部分:

    • 每次取出 \(q_1,q_2\) 队尾元素中的较强者作为最强蛇,以及 \(q_1\) 队首元素作为最弱蛇,由于这一部分中所有最强蛇吃完最弱蛇后,都不是最弱蛇,因此这一轮的最弱蛇肯定没有吃过别人,即,在队列 \(q_1\) 中。
    • 我们计算出最强蛇吃完最弱蛇的实力,如果小于现在 \(q_1\) 队首的实力就进入第二部分,否则将它塞入 \(q_2\) 队首。根据之前的推论,此时吃完最弱蛇的最强蛇的实力,肯定比上一轮吃完最弱蛇的最强蛇实力更菜。
  • 第二部分:
    • 我们直接取出 \(q_1,q_2\) 的队尾,由于最弱蛇就是上一轮中吃完最弱蛇的最强蛇,因此我们不用取出 \(q_1/q_2\) 的队首元素,而是直接取出上一次吃掉别人的蛇即可。
    • 还是计算出最强蛇吃完最弱蛇的实力,如果此时这条蛇的实力比当前最弱蛇的实力强就退出,根据第二部分轮数的奇偶性判断是否令答案减一。否则继续重复上一步的过程。

时间复杂度 \(\sum n\)。

const int MAXN=1e6;
int n,a[MAXN+5];bool fst=0;
deque<pii> q1,q2;
pii getmx(){
pii p;
if(q1.empty()) return p=q2.back(),q2.ppb(),p;
if(q2.empty()) return p=q1.back(),q1.ppb(),p;
if(q2.back()>q1.back()) return p=q2.back(),q2.ppb(),p;
return p=q1.back(),q1.ppb(),p;
}
void solve(){
if(!fst){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
} else {
int c;scanf("%d",&c);
while(c--){
int x,y;scanf("%d%d",&x,&y);
a[x]=y;
}
} fst=1;
while(!q1.empty()) q1.ppb();
while(!q2.empty()) q2.ppb();
for(int i=1;i<=n;i++) q1.push_back(mp(a[i],i));
// for(int i=1;i<=n;i++) printf("%d%c",a[i]," \n"[i==n]);
while(1){
if(q1.size()+q2.size()<=2) return puts("1"),void();
pii p=getmx();
int y=q1.front().fi;q1.pop_front();
if(q1.empty()||mp(p.fi-y,p.se)<q1.front()){
int cnt=0,res=q1.size()+q2.size()+1,pre=p.fi-y;
while(1){
cnt++;
if(q1.size()+q2.size()<2){
if(cnt&1) res++;
printf("%d\n",res);
return;
} pii nwp=getmx();
if((q1.empty()||mp(nwp.fi-pre,nwp.se)<q1.front())&&
(q2.empty()||mp(nwp.fi-pre,nwp.se)<q2.front()));
else {
if(cnt&1) res++;
printf("%d\n",res);
return;
} pre=nwp.fi-pre;
}
} else q2.push_front(mp(p.fi-y,p.se));
} assert(0);
}
int main(){
// freopen("snakes4.in","r",stdin);
int qu;scanf("%d",&qu);
while(qu--) solve();
return 0;
}

洛谷 P7078 - [CSP-S2020] 贪吃蛇(贪心)的更多相关文章

  1. 洛谷 P2503 [HAOI2006]均分数据 随机化贪心

    洛谷P2503 [HAOI2006]均分数据(随机化贪心) 现在来看这个题就是水题,但模拟赛时想了1个小时贪心,推了一堆结论,最后发现贪心做 不了, 又想了半个小时dp 发现dp好像也做不了,在随机化 ...

  2. 洛谷P3602 Koishi Loves Segments(贪心,multiset)

    洛谷题目传送门 贪心小水题. 把线段按左端点从小到大排序,限制点也是从小到大排序,然后一起扫一遍. 对于每一个限制点实时维护覆盖它的所有线段,如果超过限制,则贪心地把右端点最大的线段永远删去,不计入答 ...

  3. 洛谷P4155 [SCOI2015]国旗计划(贪心,树形结构,基数排序)

    洛谷题目传送门 \(O(n)\)算法来啦! 复杂度优化的思路是建立在倍增思路的基础上的,看看楼上几位巨佬的描述吧. 首先数组倍长是一样的.倍增法对于快速找到\(j\)满足\(l_j+m\le r_i\ ...

  4. 【题解】洛谷P2577 [ZJOI2005] 午餐(DP+贪心)

    次元传送门:洛谷P2577 思路 首先贪心是必须的 我们能感性地理解出吃饭慢的必须先吃饭(结合一下生活) 因此我们可以先按吃饭时间从大到小排序 然后就能自然地想到用f[i][j][k]表示前i个人在第 ...

  5. BZOJ 2460 & 洛谷 P4570 [BJWC2011]元素 (线性基 贪心)

    题目链接: 洛谷 BZOJ 题意 给定 \(n\) 个矿石,每个矿石有编号和魔力值两种属性,选择一些矿石,使得魔力值最大且编号的异或和不为 0. 思路 线性基 贪心 根据矿石的魔力值从大到小排序. 线 ...

  6. 洛谷 P5470 - [NOI2019] 序列(反悔贪心)

    洛谷题面传送门 好几天没写题解了,写篇题解意思一下(大雾 考虑反悔贪心,首先我们考虑取出 \(a,b\) 序列中最大的 \(k\) 个数,但这样并不一定满足交集 \(\ge L\) 的限制,因此我们需 ...

  7. 【题解】洛谷P1080 [NOIP2012TG] 国王游戏(贪心+高精度)

    次元传送门::洛谷P1080 思路 我们模拟一下只有两个大臣的时候发现 当a1​∗b1​<a2​∗b2​是ans1<ans2 所以我们对所有大臣关于左右手之积进行排序 得到最多钱的大臣就是 ...

  8. 洛谷P3817 小A的糖果 贪心思想

    一直觉得洛谷的背景故事很....直接题解吧 #include <bits/stdc++.h> //万能头文件 using namespace std; int a[100002]; // ...

  9. 洛谷P7078 [CSP-S2020] 贪吃蛇 题解

    比赛里能做出这题的人真的非常厉害,至少他的智商和蛇一样足够聪明. 首先有一个结论: 当前最强的蛇吃了最弱的蛇之后,如果没有变成最弱的蛇,他一定会选择吃! 证明: 假设当前最强的蛇叫石老板. 如果下一条 ...

随机推荐

  1. springboot 事务执行全流程分析

    springboot 事务执行全流程分析 目录 springboot 事务执行全流程分析 1. 事务方法执行前的准备工作 2. 业务代码的调用 3. 事务方法执行后处理 4. 业务代码在事务和非事务中 ...

  2. STM32直流电机启动(一)驱动电路的介绍

    驱动电路 典型的H桥驱动电路如下:要使电机旋转只需导通对角线上的两个三极管即可,如导通Q1,Q4,关闭Q2,Q4即可驱动电机正转:若想电机反向转动,即导通三极管Q2,Q3,关闭Q1,Q4.此时电路图可 ...

  3. 云效Flow如何实现阿里云ECS多环境发布

    一.背景 云效Flow基于标签功能实现阿里云ECS多环境发布,在软件开发和部署过程中,我们的软件往往需要在不同的运行环境中运行,例如:开发人员本地开发环境.测试团队的测试环境.还有类生产环境和生产环境 ...

  4. greenplum分布键的hash值计算分析

    greenplum 数据分布策略 greenplum 是一个 MPP 架构的数据库,由一个 master 和多个 segment 组成(还可选配置一个 standby master),其数据会根据设置 ...

  5. 51nod_1003 阶乘后面0的数量(求N!中5的个数,数论)

    题意: n的阶乘后面有多少个0? 6的阶乘 = 1*2*3*4*5*6 = 720,720后面有1个0.   Input 一个数N(1 <= N <= 10^9) OutPut 输出0的数 ...

  6. hdu 1394 Minimum Inversion Number(线段树or树状数组)

    题意: 给你N个数,N个数是0~N-1的一个全排列. 要求统计它的所有形式的逆序对的最小值.它的所有形式的意思是,不断将数组开头的第一个数放到数组的最后面. 逆序对:i<j且ai>aj 思 ...

  7. QuantumTunnel:协议路由 vs 端口路由

    本篇来聊一下内网穿透中流量转发的问题 内网穿透和核心逻辑是根据流量的路由信息准确地将公网流量路由到指定的机器端口上,从而完成一次流量的内网穿透. 这里有一个核心问题,路由信息从哪里获取? 常见的有将路 ...

  8. spark搭建

    1.上传解压,配置环境变量 配置bin目录 2.修改配置文件 conf cp spark-env.sh.template spark-env.sh 增加配置 export SPARK_MASTER_I ...

  9. yrm的安装和使用

    yrm的安装和使用 我们经常下载包的速度很忙有的还会卡住几十分钟,所以我们需要切换镜像,这样我们下载的速度会快很多 而yrm 是一个 yarn源管理器,允许你快速地在源间切换 安装 npm insta ...

  10. sm2加密

    import java.math.BigInteger; import java.security.NoSuchAlgorithmException; import java.security.Sec ...