题目分析

朴素的做法就是预处理下一个目的地,然后跑模拟,超时。

本题最重要的考点是倍增优化。设$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提高组】开车旅行 倍增的更多相关文章

  1. [NOIP2012提高组]开车旅行

    题目:洛谷P1081.Vijos P1780.codevs1199. 题目大意:有n座海拔高度不相同的城市(编号1~n),两城市的距离就是两城市海拔之差.规定每次只能从编号小的城市走到编号大的城市. ...

  2. 刷题总结——疫情控制(NOIP2012提高组)

    题目: 题目背景 NOIP2012 提高组 DAY2 试题. 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都 ...

  3. GZOJ 1361. 国王游戏【NOIP2012提高组DAY1】

    国王游戏[NOIP2012提高组DAY1] Time Limit:1000MS Memory Limit:128000K Description 国王游戏(game.cpp/c/pas) [问题描述] ...

  4. 【NOIP2015模拟11.5】JZOJ8月5日提高组T3 旅行

    [NOIP2015模拟11.5]JZOJ8月5日提高组T3 旅行 题目 若不存在第\(k\)短路径时,输出"Stupid Mike" 题解 题意 给出一个有\(n\)个点的树 问这 ...

  5. [NOIP2012] 提高组 洛谷P1081 开车旅行

    题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 ...

  6. P1081 [NOIP2012]开车旅行[倍增]

    P1081 开车旅行    题面较为啰嗦.大概概括:一个数列,只能从一个点向后走,两种方案:A.走到和自己差的绝对值次小的点B.走到和自己差的绝对值最小点:花费为此差绝对值:若干询问从规定点向后最多花 ...

  7. NOIP2012 提高组 Day 1

    期望得分:100+100+70=270 实际得分:100+50+70=220 T2 没有底 最后剩余时间来不及打高精.思路出现错误 T1 Vigenère 密码 题目描述 16 世纪法国外交家 Bla ...

  8. NOIP2012提高组

    D1T1.Vigenère密码 模拟 #include<iostream> #include<cstdio> using namespace std; int main() { ...

  9. 洛谷P1084 [NOIP2012提高组Day2T3]疫情控制

    P1084 疫情控制 题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控 ...

  10. [NOIP2012] 提高组 洛谷P1084 疫情控制

    题目描述 H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都, 也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散 ...

随机推荐

  1. [置顶] WebService学习总结(3)——使用java JDK开发WebService

    一.WebService的开发手段 使用Java开发WebService时可以使用以下两种开发手段 1. 使用JDK开发(1.6及以上版本) 2.使用CXF框架开发(工作中) 二.使用JDK开发Web ...

  2. 【例题 6-13 UVA - 1103】Ancient Messages

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 每个图案里面的"洞"的个数都是不同的. 则可以根据这个判别每个图像是什么. 先用dfs确定轮廓之后. 再从每个白 ...

  3. cURL(wget)—— 测试 RESTful 接口及模拟 GET/POST/PUT/DELETE/OPTIONS 请求

    cURL 是一个简单的 http 命令行工具.与最优秀的 Unix 工具一样,在设计之时,cURL 是个小型程序,功能十分专一,而且是故意为之,仅用于访问 http 服务器.(在 Linux 中,可以 ...

  4. spark源码解析之scala基本语法

    1. scala初识 spark由scala编写,要解析scala,首先要对scala有基本的了解. 1.1 class vs object A class is a blueprint for ob ...

  5. smack capable(CAP_MAC_OVERRIDE)

    https://blog.csdn.net/ning_wei/article/details/9670947 LINUX中的capable int smk_curacc(char *obj_label ...

  6. UVA - 1161 Objective: Berlin(最大流+时序模型)

    题目大意:有n个城市m条航线.给出每条航线的出发地,目的地,座位数,起飞时间和到达时间(所给形式为HHMM.记得转化),再给出城市A和B.和到达城市B的最晚时间.如今问一天内最多有多少人能从A飞到B, ...

  7. Redis Cluster(Redis 3.X)设计要点

    Redis 3.0.0 RC1版本号10.9号公布,Release Note这个版本号支持Redis Cluster.相信非常多同学期待已久,只是这个版本号仅仅是RC版本号,要应用到生产环境,还得等等 ...

  8. php用两个栈来实现队列

    php用两个栈来实现队列 一.总结 我主要的问题是不知道的是题目描述,题目和贵的代码之间的关系,以及返回值 思路:A栈做入队操作,B栈做出队操作,入队的时候元素直接入A,出队的时候判断B栈是否为空,如 ...

  9. vue项目build后font-awesome不显示问题

    解决办法: 修改build目录下的utils.js:添加 publicPath: '../../' // Extract CSS when that option is specified // (w ...

  10. ng-cli搭建angular项目框架

    原文地址 https://www.jianshu.com/p/0a8f4b0f29b3 环境准备 以下步骤都不需要事先创建文件夹,只是环境的准备过程,只有到需要搭建项目的时候才需要创建文件夹用来存放项 ...