【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 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散 ...
随机推荐
- ajax 通过return 返回data值
方法例如以下: 1. ajax 必须为同步 设置async:false 2. 定一个局部变量 把data赋值给局部变量 然后 return 局部变量就可以 示比例如以下 function getEmp ...
- LuceneIndexFileDeleter会保留初始的commit
给实时索引加入了merge策略,持续更新时发现有做merge,但索引文件夹中的段数远远大于RealTimeIndexWriter中的段数,就是有些merge的段应该删除,文件夹中没有删除.而关闭sea ...
- WinXP局域网共享设置
关闭局域网共享 1.不允许SAM帐户和共享的匿名枚举(系统默认是允许的). 组策略-计算机配置-Windows 设置-安全设置-本地安全策略-安全选项-网络访问:不允许SAM帐户和共享的匿名枚举. 设 ...
- 使用MongoDb连接数据库服务器
链接MongoDb数据库服务器的字符串格式: mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN] ...
- 利用Attribute实现Aop
Aop“面向切面编程”,与OOP“面向对象编程”一样是一种编程思路.个人理解:在不改变原有逻辑的基础上,注入其他行为. 基础代码(仿MVC拦截器实现) namespace HGL.Toolkit.Ao ...
- DOS 命令forfiles
forfiles /p E:/dbbackup/diff /s /m *.* /d -14 /c "cmd /c del @file" forfiles: /p 指定的路径 /s ...
- 1、初识python
1.linux下运行python脚本时,在第一行通过“#!/usr/bin/env python”指定python h.py <=> ./h.py 具有相同的效果 (h.py需要有执行权限 ...
- IOS计算两点之间的距离
//广州经纬度 CLLocationCoordinate2D guangZhouLocation; guangZhouLocation.latitude = 23.20; guangZhouLocat ...
- Spring Boot初步认识
Spring Boot 来源及背后 Spring Boot开发始于 2013 年,伴随Spring4.0而生,2014 年 4 月发布 1.0.0 版本.当前版本1.4.0,http://projec ...
- 高并发解决方案--负载均衡(HTTP,DNS,反向代理服务器)(解决大流量,高并发)
高并发解决方案--负载均衡(HTTP,DNS,反向代理服务器)(解决大流量,高并发) 一.总结 1.什么是负载均衡:当一台服务器的性能达到极限时,我们可以使用服务器集群来提高网站的整体性能.那么,在服 ...