题面传送门

题意:

  • 有 \(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. 4.1 The Example Domain 领域示例代码

    4.1 The Example Domain 领域示例代码 The examples will use some concepts those are used by GitHub, like Iss ...

  2. 分享一份软件测试项目实战(web+app+h5+小程序)

    大家好,我是谭叔. 本次,谭叔再度出马,给大家找了一个非常适合练手的软件测试项目,此项目涵盖web端.app端.h5端.小程序端,可以说非常之全面. 缘起 在这之前,谭叔已经推出了九套实战教程. 但是 ...

  3. kivy Label触发事件

    kivy  label也可以触发事件,为什么只有我这么无聊学垃圾kivy """ 在通过ref标记一段文本后点击这段文本就可以触发'on_ref_press'事件,在该事 ...

  4. LeetCode:并查集

    并查集 这部分主要是学习了 labuladong 公众号中对于并查集的讲解,文章链接如下: Union-Find 并查集算法详解 Union-Find 算法怎么应用? 概述 并查集用于解决图论中「动态 ...

  5. csp-s 2021

    T1 廊桥分配 当一架飞机抵达机场时,可以停靠在航站楼旁的廊桥,也可以停靠在位于机场边缘的远机位. 乘客一般更期待停靠在廊桥,因为这样省去了坐摆渡车前往航站楼的周折. 然而,因为廊桥的数量有限,所以这 ...

  6. Less-5闯关失败

    进行第五关的通关还是用之前的方式进行测试以及判断是什么类型的注入.通过判断我们不难发现是字符型注入.但是出了问题,我们会发现按照原来的步骤进行注入都会返回"You are in " ...

  7. MySQL怎么缓解读的压力的?---buffer pool

    每当我们想要缓解读,一般会想到什么? 预读取,缓存 缓存 缓存,其实就是将高频访问的数据放到内存里面,减少读盘的次数. 为了提高内存的利用率,MySQL还建立了缓存池,也就是buffer pool,存 ...

  8. Redis INFO CPU 信息详解

    一.INFO CPU 通过INFO CPU命令可以查看Redis进程对于CPU的使用情况,如下: 这几个字段的含义如下所示: used_cpu_sys: System CPU consumed by ...

  9. spark搭建

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

  10. makefile简单学习(一)

    第一层 显式规则 目标:依赖 [tab] 指令 伪目标:.PHONY: 递归规则 hello : hello.o gcc hello.o -o hello hello.o : hello.s gcc ...