题面

题解

先看数据,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. torch.tensor(),torch.Tensor()

    Pytorch tensor操作 https://www.cnblogs.com/jeshy/p/11366269.html    我们需要明确一下,torch.Tensor()是python类,更明 ...

  2. Dcoker镜像管理与容器应用

    Dcoker镜像管理与容器应用 docker基于镜像创建容器 相同版本的镜像只允许存在一个 同一个镜像可以创建多个容器 镜像管理 [root@localhost ~]# docker pull cen ...

  3. Mybatisi和Spring整合源码分析

    一.MybatisSpring的使用 1.创建 Maven 工程. 2.添加依赖,代码如下 <dependency> <groupId>org.mybatis</grou ...

  4. BUUCTF-snake

    snake 这是我最想吐槽的一个题目,搞这个蛇在这里.我看的这个图就头皮发麻. 最不愿意做的题,建议以后出题能不能搞个正常的啊. 16进制打开发现压缩包,binwalk提取,得到三个文件 key中是b ...

  5. vue-cli在webpack环境下怎样生成开发环境模板(适合初学者)

    1.事先安装好cnpm(淘宝镜像) npm install -g cnpm --registry=https://registry.npm.taobao.org 这是网址,可以自己用命令行工具输入命令 ...

  6. Linux安装MySQL,数据库工具连接Linux的MySQL

    1.centOS中默认安装了MariaDB,需要先进行卸载 rpm -qa | grep -i mariadb rpm -e --nodeps 上面查出来的mariadb 2.下载MySQL仓库并安装 ...

  7. idea 内置tomcat jersey 跨服务器 上传文件报400错误

    报错内容 com.sun.jersey.api.client.UniformInterfaceException: PUT http://.jpg returned a response status ...

  8. springboot 中如何正确在异步线程中使用request

    起因: 有后端同事反馈在异步线程中获取了request中的参数,然后下一个请求是get请求的话,发现会偶尔出现参数丢失的问题. 示例代码: @GetMapping("/getParams&q ...

  9. 字符串运算符&&三元运算符

    public class Demo01 { public static void main(String[] args) { //字符串连接符 + String int a=20; int b=10; ...

  10. 第一天python3 封装和解构

    封装 将多个值使用逗号分割,组合在一起:本质上,返回一个元组,只是省略了小括号:python特有语法,被很多语言学习和借鉴;比如javascript:t1=(1,2) 定义为元组:t2=1,2 将1和 ...