「CERC2017」Donut Drone
题目链接
题目翻译:
你正在模拟无人机探索一个不稳定的环状行星的过程。技术上说,无人机正在穿过一个环形网格———一个在两维上都首尾环绕在一起的矩形网格。格子的行号从上到下依次编号为\(1\)到\(r\),列号
从上到下依次编号为\(1\)到\(c\)。每个格子还有一个海拔——这是个正数。
无人机一开始位于第一行第一列的格子。每一步,无人机会考虑这样三个格子:右边、右上方、右下方(注意这个网格首尾相接)。无人机会飞到它们之中海拔最高的一个格子。模拟的过程中,共有两种可能的操作:
\(move\) \(k\)无人机移动k步
\(change\) \(a\) \(b\) \(e\)第\(a\)行第\(b\)列的格子海拔修改为\(e\)。
在每次\(move\)操作后,你都需要立刻找到无人机的位置。你可以认为,每次移动的三个目标位置海拔互不相同,因此每一步移动都是良定义的。
solution
每次移动的步数\(k\)很大,所以可以联想到倍增跳法,即每次跳\(2^k\)步。
但步数不太好维护,我们考虑将移动\(k\)步转化为先暴力跳到第一列,再从第一列出发跳若干圈,最后在暴力跳剩下的不到一圈的步数。显然2段暴力跳的复杂度仅为\(O(c)\),可以接受
那么问题转化为了要维护从第一列的每一个位置出发跳\(2^k\)圈后所处的位置。本题在\(y轴\)上的跳法不确定,但在\(x\)轴上一直是每次向右移动一格,于是可以在列上建立线段树,每个节点(设对应的列为\(l,r\))维护第\(l\)列上每个位置,跳到第\(r+1\)列后所处的位置,就可以
t[p][i]=t[p<<1|1][t[p<<1][i]]
实现转移(其中\(t[p][i]\)表示处在第\(i\)行的点,跳过\(p\)对应的这段区间后所处的位置,在代码中是\(T[p].t[i]\))
于是根节点维护的答案就是第一列中的每个位置跳一圈后所处的位置,接下来的只不过是倍增基本套路。
每次对\((x,y)\)的修改只会影响第\(x-1\)列维护的答案,等于是线段树中的单点修改,复杂度\(O(rlog(c))\)
code
#include<bits/stdc++.h>
using namespace std;
const int N=5010;
int a[N][N],ans[N][N],R,C,m,to[N][32];
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
struct SGT{
struct tree{
int t[N];
}T[N<<2];
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (l+r>>1)
inline void pushup(int p){
for(int i=1;i<=R;++i)
T[p].t[i]=T[rc].t[T[lc].t[i]];
}
inline void build(int p,int l,int r){
if(l==r){
for(int i=1;i<=R;++i) T[p].t[i]=ans[l][i];
return ;
}
build(lc,l,mid);
build(rc,mid+1,r);
pushup(p);
}
inline void update(int p,int l,int r,int x){
if(l==r){
for(int i=1;i<=R;++i) T[p].t[i]=ans[l][i];
return ;
}
if(x<=mid) update(lc,l,mid,x);
else update(rc,mid+1,r,x);
pushup(p);
}
#undef lc
#undef rc
#undef mid
}T;
inline void work(int &x,int &y){
int yy=y==C?1:y+1,x1=x>1?x-1:R,x2=x,x3=x==R?1:x+1;
int ans=a[x1][yy],pos=x1;
if(a[x2][yy]>ans) ans=a[x2][yy],pos=x2;
if(a[x3][yy]>ans) ans=a[x3][yy],pos=x3;
x=pos;y=yy;
}
int main(){
R=read();C=read();
for(int i=1;i<=R;++i)
for(int j=1;j<=C;++j)
a[i][j]=read();
for(int i=1;i<=R;++i){
for(int j=1;j<=C;++j){
int x=i,y=j;work(x,y);
ans[j][i]=x;
}
}
T.build(1,1,C);
for(int i=1;i<=R;++i) to[i][0]=T.T[1].t[i];
for(int j=1;j<=30;++j)
for(int i=1;i<=R;++i)
to[i][j]=to[to[i][j-1]][j-1];
m=read();
int nx=1,ny=1;
while(m--){
char s[10];scanf("%s",s);
if(s[0]=='c'){
int x=read(),y=read(),e=read();
a[x][y]=e;y=y>1?y-1:C;
for(int i=1;i<=R;++i){
int t1=i,t2=y;
work(t1,t2);
ans[y][i]=t1;
}
T.update(1,1,C,y);
for(int i=1;i<=R;++i) to[i][0]=T.T[1].t[i];
for(int j=1;j<=30;++j)
for(int i=1;i<=R;++i)
to[i][j]=to[to[i][j-1]][j-1];
}
if(s[0]=='m'){
int k=read();
while(k&&ny!=1) work(nx,ny),k--;
int circle=k/C;k=k%C;
for(int i=30;i>=0;--i) if(circle&(1<<i)) circle^=(1<<i),nx=to[nx][i];
while(k--) work(nx,ny);
printf("%d %d\n",nx,ny);
}
}
return 0;
}
「CERC2017」Donut Drone的更多相关文章
- 「译」JUnit 5 系列:条件测试
原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...
- 「译」JUnit 5 系列:扩展模型(Extension Model)
原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...
- JavaScript OOP 之「创建对象」
工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...
- 「C++」理解智能指针
维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...
- 「JavaScript」四种跨域方式详解
超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...
- 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management
写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...
- 「2014-3-18」multi-pattern string match using aho-corasick
我是擅(倾)长(向)把一篇文章写成杂文的.毕竟,写博客记录生活点滴,比不得发 paper,要求字斟句酌八股结构到位:风格偏杂文一点,也是没人拒稿的.这么说来,arxiv 就好比是 paper 世界的博 ...
- 「2014-3-17」C pointer again …
记录一个比较基础的东东-- C 语言的指针,一直让人又爱又恨,爱它的人觉得它既灵活又强大,恨它的人觉得它太过于灵活太过于强大以至于容易将人绕晕.最早接触 C 语言,还是在刚进入大学的时候,算起来有好些 ...
- 「2014-3-13」Javascript Engine, Java VM, Python interpreter, PyPy – a glance
提要: url anchor (ajax) => javascript engine (1~4 articles) => java VM vs. python interpreter =& ...
随机推荐
- 050_Dos命令
目录 Dos命令 打开Dos控制台 管理员方式运行 常用的Dos命令 Dos命令 打开Dos控制台 开始->附件->命令提示符 Window+R 输入cmd(推荐使用) 在任意文件夹下-& ...
- .NET CORE 3.1.5 跨域设置
1.Startup配置 1 #region 跨域设置 2 //注意:放到services.AddMvc()之前 3 services.AddCors(options => { 4 options ...
- STM32入门系列-使用C语言封装寄存器
前面文章介绍了存储器映射.寄存器和寄存器映射,这些都是为了介绍使用 C语言封装寄存器做铺垫.这里我们通过一个实例来对 C 语言封装寄存器进行介绍. 具体实例:控制 GPIOC 端口的第 0 管脚输出一 ...
- Struts2 S2-059 (CVE-2019-0230 )复现 及流量分析、特征提取
一.简介 2020年08月13日,Apache官方发布了Struts2远程代码执行漏洞的风险通告,该漏洞编号为CVE-2019-0230,漏洞等级:高危,漏洞评分:8.5 二.漏洞描述 Struts2 ...
- 技术总监的故事告诉大家,要学会say【NO!】
今天就给大家分享一个发生在我自己身上的事情吧. 1 2015年的时候,我和我的领导A,还有几个小伙伴正在做一个"紧急定制",这个任务是公司老大CEO和重要客户定下来的一个项目,背后 ...
- P1948 [USACO08JAN]Telephone Lines S
题意描述 在无向图中求一条从 \(1\) 到 \(N\) 的路径,使得路径上第 \(K+1\) 大的边权最小. 等等,最大的最小...如此熟悉的字眼,难道是 二分答案. 下面进入正题. 算法分析 没错 ...
- ThreadLocal原理大解析
今天呢,和大家聊一下ThreadLocal. 1. 是什么? JDK1.2提供的的一个线程绑定变量的类. 他的思想就是:给每一个使用到这个资源的线程都克隆一份,实现了不同线程使用不同的资源,且该资源之 ...
- pycharm新建项目时选择virtualenv的说明
虚拟环境及venv和virtualenv介绍:https://www.cnblogs.com/mind18/p/13877170.html pip介绍:https://www.cnblogs.com/ ...
- monkey及其的日志管理和分析
1. monkey 1.1. 介绍 通过monkey程序模拟用户触摸屏幕,滑动Trackball.按键等操作来对设备上的程序进行压力测试,检测程序多久的时间会发生异常,检查和评估被测程序的稳定性 ...
- 重拾python所要知道的一些主干知识点
前言:因为有一段时间没有用python了,最近需要用到,只能回头过去看B站视频补一补,因为语言都是相通的,而且一些细节都可以去查表解决,所以呢,我们只需要知道一些python与其他语言的不同和常见的优 ...