【NOIP2012提高组】开车旅行 倍增
题目分析
朴素的做法就是预处理下一个目的地,然后跑模拟,超时。
本题最重要的考点是倍增优化。设$fa[i][j]$表示a从i出发行驶$2^j$“次”后行驶的路程,$fb[i][j]$表示从i出发行驶$2^j$“次”后行驶的路程,注意这里的"次",a、b交替行驶。$f[i][j]$表示从i出发a、b交替$2^j$“次”后行驶到的城市编号。
显然有$fa[i][j] = fa[i][j - 1] + fa[f[i][j - 1]][j - 1], fb = fb[i][j - 1] + fb[f[i][j - 1]], f[i][j] = ff[i][j - 1]][j - 1]$。只需要用set求出前驱后继和次前驱后继,就能正确预处理出来。最后在路径上跑倍增就行。
code
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<set>
using namespace std; const int N = 1e5 + ;
int n, x0, m, nxta[N], nxtb[N], f[N][];
typedef long long ll;
ll fa[N][], fb[N][];
struct node2{
int h, pos;
inline bool operator < (const node2 &b) const{
return h < b.h;
}
}data[N];
struct node{
int pos, dis;
inline bool operator < (const node &b) const{
if(dis != b.dis) return dis < b.dis;
return data[pos].h < data[b.pos].h;
}
}t[];
set<node2> S; inline int read(){
int i = , f = ; char ch = getchar();
for(; (ch < '' || ch > '') && ch != '-'; ch = getchar());
if(ch == '-') f = -, ch = getchar();
for(; ch >= '' && ch <= ''; ch = getchar())
i = (i << ) + (i << ) + (ch - '');
return i * f;
} inline void wr(ll x){
if(x < ) putchar('-'), x = -x;
if(x > ) wr(x / );
putchar(x % + '');
} inline void Find(int x){
int cnt = ;
set<node2>::iterator it = S.find(data[x]);
if(it != S.begin()){
--it;
t[++cnt] = (node){it->pos, abs(data[x].h - it->h)}; if(it != S.begin()) {
--it;
t[++cnt] = (node){it->pos, abs(data[x].h - it->h)};
++it;
}
++it;
}
if((++it) != S.end()){
t[++cnt] = (node){it->pos, abs(it->h - data[x].h)};
if((++it) != S.end()){
t[++cnt] = (node){it->pos, abs(it->h - data[x].h)};
--it;
}
--it;
}
sort(t + , t + cnt + );
nxtb[x] = t[].pos;
if(cnt > )
nxta[x] = t[].pos;
} inline void init(){
for(int i = ; i <= n; i++){
int na = nxta[i], nb = nxtb[na];
fa[i][] = na ? abs(data[na].h - data[i].h) : ;
fb[i][] = nb ? abs(data[nb].h - data[na].h) : ;
f[i][] = nb;
}
for(int j = ; j <= ; j++)
for(int i = ; i <= n; i++){
f[i][j] = f[f[i][j - ]][j - ];
fa[i][j] = fa[i][j - ] + fa[f[i][j - ]][j - ];
fb[i][j] = fb[i][j - ] + fb[f[i][j - ]][j - ];
}
} inline void query(int s, ll x, ll &na, ll &nb){
for(int i = ; i >= ; i--)
if(f[s][i] && fa[s][i] + fb[s][i] <= x){
na += fa[s][i], nb += fb[s][i];
x -= fa[s][i] + fb[s][i];
s = f[s][i];
}
int posa = nxta[s], d = abs(data[s].h - data[posa].h);
if(posa && d <= x) na += d;
} int main(){
n = read();
for(int i = ; i <= n; i++) data[i] = (node2){read(), i};
for(int i = n; i >= ; i--){
S.insert(data[i]);
if(i ^ n) Find(i);
}
init();
x0 = read();
int ans = ;
ll ansa = , ansb = ;
for(int i = ; i <= n; i++){
ll na = , nb = ;
query(i, x0, na, nb);
if(!ans || ansa * nb > ansb * na) ans = i, ansa = na, ansb = nb;
}
wr(ans), putchar('\n');
m = read();
for(int i = ; i <= m; i++){
ll na = , nb = ;
int st = read(), x = read();
query(st, x, na, nb);
wr(na), putchar(' '), wr(nb), putchar('\n');
}
return ;
}
【NOIP2012提高组】开车旅行 倍增的更多相关文章
- [NOIP2012提高组]开车旅行
题目:洛谷P1081.Vijos P1780.codevs1199. 题目大意:有n座海拔高度不相同的城市(编号1~n),两城市的距离就是两城市海拔之差.规定每次只能从编号小的城市走到编号大的城市. ...
- 刷题总结——疫情控制(NOIP2012提高组)
题目: 题目背景 NOIP2012 提高组 DAY2 试题. 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都 ...
- GZOJ 1361. 国王游戏【NOIP2012提高组DAY1】
国王游戏[NOIP2012提高组DAY1] Time Limit:1000MS Memory Limit:128000K Description 国王游戏(game.cpp/c/pas) [问题描述] ...
- 【NOIP2015模拟11.5】JZOJ8月5日提高组T3 旅行
[NOIP2015模拟11.5]JZOJ8月5日提高组T3 旅行 题目 若不存在第\(k\)短路径时,输出"Stupid Mike" 题解 题意 给出一个有\(n\)个点的树 问这 ...
- [NOIP2012] 提高组 洛谷P1081 开车旅行
题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 ...
- P1081 [NOIP2012]开车旅行[倍增]
P1081 开车旅行 题面较为啰嗦.大概概括:一个数列,只能从一个点向后走,两种方案:A.走到和自己差的绝对值次小的点B.走到和自己差的绝对值最小点:花费为此差绝对值:若干询问从规定点向后最多花 ...
- NOIP2012 提高组 Day 1
期望得分:100+100+70=270 实际得分:100+50+70=220 T2 没有底 最后剩余时间来不及打高精.思路出现错误 T1 Vigenère 密码 题目描述 16 世纪法国外交家 Bla ...
- NOIP2012提高组
D1T1.Vigenère密码 模拟 #include<iostream> #include<cstdio> using namespace std; int main() { ...
- 洛谷P1084 [NOIP2012提高组Day2T3]疫情控制
P1084 疫情控制 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控 ...
- [NOIP2012] 提高组 洛谷P1084 疫情控制
题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都, 也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散 ...
随机推荐
- Java网络编程之TCP、UDP
Java网络编程之TCP.UDP 2014-11-25 15:23 513人阅读 评论(0) 收藏 举报 分类: java基础及多线程(28) 版权声明:本文为博主原创文章,未经博主允许不得转载. ...
- COGS——C2274. [HEOI 2016] tree
http://www.cogs.pro/cogs/problem/problem.php?pid=2274 ★☆ 输入文件:heoi2016_tree.in 输出文件:heoi2016_tre ...
- POJ 2386 Lake Counting DFS水水
http://poj.org/problem?id=2386 题目大意: 有一个大小为N*M的园子,雨后积起了水.八连通的积水被认为是连接在一起的.请求出院子里共有多少水洼? 思路: 水题~直接DFS ...
- (转) 通过UUID在vSphere虚拟机内外识别硬盘
转自:http://ju.outofmemory.cn/entry/28398 简单介绍下应用场景:开发基于虚拟化IaaS的一些应用就免不了要跟虚拟机(VM)打交道,因为VM逻辑上独立于宿主机(hos ...
- [NodeJS] Use Secrets When Deploying Applications with Now
Applications require a lot of sensitive information. Database passwords, API keys and secrets used f ...
- (素材源代码) 猫猫学IOS(五)UI之360等下载管理器九宫格UI
猫猫分享,必须精品 先看效果 代码学习地址: 猫猫学IOS(五)UI之360等下载管理器九宫格UI 猫猫学IOS(五)UI之360等下载管理器九宫格UI http://blog.csdn.net/u0 ...
- 9.7 Binder系统_c++实现_编写程序
参考文件:frameworks\av\include\media\IMediaPlayerService.h (IMediaPlayerService,BnMediaPlayerService)fra ...
- Dll的链接使用细节
关于Dll Dll.Exe 都是PE格式的二进制文件. Dll相当于Linux操作系统下的so文件 1 基地址(Base Address)和相对地址(RelativeVirtual Address) ...
- 解决java中ZipFile解压缩时候的中文路径和乱码问题
JAVA中对jar文件或zip文件解压的时候,能够使用JDK内置的API:JarFile和ZipFile,在windows下解压这2种格式文件的时候,常常报下面错误: Exception in thr ...
- hadoop调优之一:概述 分类: A1_HADOOP B3_LINUX 2015-03-13 20:51 395人阅读 评论(0) 收藏
hadoop集群性能低下的常见原因 (一)硬件环境 1.CPU/内存不足,或未充分利用 2.网络原因 3.磁盘原因 (二)map任务原因 1.输入文件中小文件过多,导致多次启动和停止JVM进程.可以设 ...