题面

题解

先看数据,T<=10,用平衡树或优先队列是可以拿70分的,大体思路和正解思路是一样的,每次直接修改,然后模拟。

我们模拟的时候,主要是在过程中算出最终被吃的有选择权的蛇的最后选择时刻和被吃时刻,然后按照最后选择时刻从大到小排序,以此判断若ans时刻该蛇已被吃,就把ans提前,

…… 模拟一次复杂度O(nlogn)

(这个博弈思路不用我推了吧?)

那怎么把模拟优化成O(n)的呢?

首先,这个蛇吃蛇的过程有特点,新变弱的蛇要放进序列中,最麻烦的是要在中间找个位置插进去……要是直接加在后面该多好!

那么我们首先考虑直接加后面的情况吧:

拿出序列中最大的一个,记为 x,最小的一个,记为 y,y 前面次小的一个,咱叫它 z

这时,发生了一件大事:我们发现 x-y <= z !!! 

把它直接放后面,于是轮到次大的 s 跟 x-y 比,

由于 s <= x → s - x <= 0,所以 s - (x-y) = y + (s - x)  <= y , 

又因为 y <= z ,堆出 s - (x-y) <= y <= z ,它又可以放到 z 后面!!! 

把 s 换为 x' , (x-y) 换为 y',s - (x-y)就为新的 (x' - y') ,然后倒回第一个“”的那一排,于是循环开始了……

! 

得出结论:一旦过程中最大的蛇 - 最小的蛇 可以放在最后,那么直到游戏结束,所有的新蛇都可以放在最后

好那么之前,在还不能放最后的时间里,所有的新蛇都得插入序列中了!

……

真烦,先把它放一边吧!

把新蛇单独放到第二个队列里,记原序列为A1~n,此时的最大需要在两个队列开头比较,最小需要在两个队尾比较

在不能放最后的时间里,An 、An-1、An-2 ... 一定依次作为最小的蛇被吃(如果中途有新蛇能放在最后的话,你懂的,如果是B队列最后一个当最小,看下面的推导),

由于选出的最大蛇一次不比一次大(这很显然嘛),最小蛇一次不比一次小(↑),那么减出来的新蛇一定单调不增!! 

那么此时可以放心地把后面的新蛇都放到 B 队列尾了!如果B队列尾的蛇被提出来了呢?那说明已经比 A队列尾小了,之前为什么不直接放A队列尾呢?

不要问我为什么两个队列仍符合前面一个队列的结论,因为它们在模拟中本质上是一个队列。

好了,正解思路已经出来了,数组模拟两个单调队列,每次找两个队列头部最大的和尾部最小的这两条蛇,战胜的新蛇能放A队尾就放A队尾,否则放B队尾。

处理出过程以后呢?我们其实可以用桶排,把蛇按最后选择时刻放桶里拍序,博弈处理……

模拟一次复杂度O(n)

总复杂度O(Tn)

CODE

#include<ctime>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 1000005
#define LL long long
#define ULL unsigned long long
#define DB double
#define ENDL putchar('\n')
LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s == '-')f=-f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
const int MOD = 1000000007;
int n,m,i,j,s,o,k;
int a[MAXN];
struct AS{
int l,r;
}as[MAXN];
bool cmp2(AS a,AS b) {return a.r < b.r;}
struct it{
int nm,id;
it(){nm = id = 0;}
it(int N,int I){nm = N;id = I;}
};
it q1[MAXN];
it q2[MAXN];
int h1,t1,h2,t2;
bool operator >(it a,it b) {return a.nm == b.nm ? (a.id > b.id) : (a.nm > b.nm);}
bool operator <(it a,it b) {return b > a;}
bool CMP(it a,it b) {return a > b;}
int bu[MAXN],cntq;
int solve() {
h1 = 1;t1 = n;
h2 = 1;t2 = 0;
cntq = 0;
// printf("root:%d\n",root);
// ENDL;
for(int i = 1;i <= n;i ++) {
q1[i] = it(a[n-i+1],n-i+1);
as[i].l = as[i].r = -1;
bu[i] = 0;
}
for(int i = n;i > 1;i --) {
it x,y;
if(h2 > t2 || (h1 <= t1 && q1[h1] > q2[h2])) x = q1[h1 ++];
else x = q2[h2 ++];
if(h2 > t2 || (h1 <= t1 && q1[t1] < q2[t2])) y = q1[t1 --];
else y = q2[t2 --];
as[y.id].r = i;
if(as[y.id].l > 0) {
bu[as[y.id].l] = y.id;
}
as[x.id].l = i;
x.nm -= y.nm;
if(x < q1[t1]) q1[++ t1] = x;
else q2[++ t2] = x;
// printf("eaten: (%d)%d ([%d,%d] [%d,%d])\n",y.id,y.nm,h1,t1,h2,t2);
}
int ans = 1;
for(int i = 1;i <= n;i ++) {
if(bu[i]) {
if(ans < as[bu[i]].r) ans = i;
}
}
return ans;
}
int main() {
// freopen("snakes.in","r",stdin);
// freopen("snakes.out","w",stdout);
srand(time(0));
int T = read()-1;
n = read();
for(int i = 1;i <= n;i ++) {
a[i] = read();
}
// sort(q0 + 1,q0 + 1 + n,CMP);
printf("%d\n",solve());
while(T --) {
m = read();
for(int i = 1;i <= m;i ++) {
s = read();o = read();
a[s] = o;
}
printf("%d\n",solve());
}
return 0;
}

CSP-S 2020 T4 贪吃蛇 (双队列模拟)的更多相关文章

  1. 小项目特供 贪吃蛇游戏(基于C语言)

    C语言写贪吃蛇本来是打算去年暑假写的,结果因为ACM集训给耽搁了,因此借寒假的两天功夫写了这个贪吃蛇小项目,顺带把C语言重温了一次. 是发表博客的前一天开始写的,一共写了三个版本,第一天写了第一版,第 ...

  2. JS高级---面向对象的编程思想(贪吃蛇梳理)

    面向对象的编程思想(贪吃蛇梳理) 模拟贪吃蛇游戏,做的项目 地图: 宽,高,背景颜色,因为小蛇和食物都是相对于地图显示的, 这里小蛇和食物都是地图的子元素, 随机位置显示, 脱离文档流的, 地图也需要 ...

  3. 多线程的Python 教程--“贪吃蛇”

    本指南的里代码可以在这里下载:  threadworms.py ,或者从  GitHub.代码需要  Python 3 或 Python 2 ,同时也需要安装  Pygame . 点击查看大版本图片 ...

  4. javascript 编写的贪吃蛇

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. Linux Curses编程实现贪吃蛇

    curses库 简单而言,提供UNIX中多种终端 操作光标和显示字符 的接口.我们常见的vi就是使用curses实现的.现在一般都用ncurses库. Linux下curses函数库    Linux ...

  6. 贪吃蛇AI

    贪吃蛇AI 作者:CodeNoob 转载请标明作者和出处 序言 前几天在网上看到一张让人涨姿势的图片,这张图片我很早以前看过,当时就觉得肯定是程序实现的,只是当时还比较渣,不会算法.这次学了java也 ...

  7. [C语言]贪吃蛇_结构数组实现

    一.设计思路 蛇身本质上就是个结构数组,数组里存储了坐标x.y的值,再通过一个循环把它打印出来,蛇的移动则是不断地刷新重新打印.所以撞墙.咬到自己只是数组x.y值的简单比较. 二.用上的知识点 结构数 ...

  8. c语言贪吃蛇详解3.让蛇动起来

    c语言贪吃蛇详解3.让蛇动起来 前几天的实验室培训课后作业我布置了贪吃蛇,今天有时间就来写一下题解.我将分几步来教大家写一个贪吃蛇小游戏.由于大家c语言未学完,这个教程只涉及数组和函数等知识点. 上次 ...

  9. python 贪吃蛇

    #!/usr/bin/python3 ''' 项目分析: -构成 -蛇Snake -实物Food -世界World -蛇和食物属于整个世界 class world: self.snake self.f ...

随机推荐

  1. 一文详解JackSon配置信息

    背景 1.1 问题 Spring Boot 在处理对象的序列化和反序列化时,默认使用框架自带的JackSon配置.使用框架默认的,通常会面临如下问题: Date返回日期格式(建议不使用Date,但老项 ...

  2. SAP Web Dynpro-调试应用程序

    您可以使用ABAP工作台中的各种工具来调试源代码. 您可以使用调试器测试Web Dynpro应用程序的所有源代码. 步骤1-要启动调试器,您必须在ABAP工作台中选择一个新的调试器. 步骤2-转到实用 ...

  3. linux服务器通过mailx邮件发送附件到指定邮箱

    shell脚本查询数据库#!/bin/bash HOSTNAME="数据库IP" PORT="端口" USERNAME="用户" PASSW ...

  4. Python爬取全球是最大的电影数据库网站IMDb数据

    在使用 Python 开发爬虫的过程中,requests 和 BeautifulSoup4(别名bs4) 应用的比较广泛,requests主要用于模拟浏览器的客户端请求,以获取服务器端响应,接收到的响 ...

  5. tail -f 、tail -F、tailf的区别

    三者经常在工作中会使用到,以下是三条命令的区别,帮忙大家理解:1.tail -f 等同于--follow=descriptor,根据文件描述符进行追踪,当文件改名或被删除,追踪停止,但是不是断开. 2 ...

  6. Intel的CPU系列说明

    至强可扩展系列是英特尔推出的新一代至强处理器系列,如今距离该系列推出几乎过去一年了.新的CPU并没有延续E系列的命名,英特尔将至强可扩展系列以金属命名,将该系列分为"铂金Platinum&q ...

  7. 关于cpu体系架构的一些有趣的故事分享

    从排查一次匪夷所思的coredump,引出各种体系架构的差异. 本文中的所有内容来自学习DCC888的学习笔记或者自己理解的整理,如需转载请注明出处.周荣华@燧原科技 1 背景 从全世界有记载的第一台 ...

  8. Java的main函数(命令行传参)

    javac :编译命令 java  :执行命令

  9. Python List 中的append 和 extend 的区别

    方法的参数不同 append 方法是向原list的末尾添加一个对象(任意对象:如元组,字典,列表等),且只占据一个原list的索引位,添加后无返回值,直接在原列表中添加. list.append(ob ...

  10. C语言课堂--现代编译环境搭建[2020年7月]

    看过了很多专家吐槽目前的大学c语言教学问题多多: 教材难懂,消磨了学生的兴趣: 环境老旧,都2020了还有在用VC6甚至TurboC 2.0,语法不规范. 轮到自己上课,心想可不能再继续这样的c语言课 ...