题目分析

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

本题最重要的考点是倍增优化。设$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. Zookeeper源码用ant进行编译为eclipse工程--转载

    原文地址:http://www.it165.net/os/html/201411/10142.html Zookeeper GitHub的下载地址是:https://github.com/apache ...

  2. [D3] SVG Graphics Containers and Text Elements in D3 v4

    SVG is a great output format for data visualizations because of its scalability, but it comes with s ...

  3. SVN—怎样安装SVNclient软件

            一.怎样安装TortoiseSVN-1.7.12.24070-win32-svn-1.7.9版本号的SVNclient软件:        a.下载TortoiseSVN-1.7.12 ...

  4. UIDeviceOrientationDidChangeNotification和UIApplicationDidChangeStatusBarFrameNotification

    这几天做App的时候,需要添加旋转屏通知以便调整UI布局 刚开始我使用的是UIDeviceOrientationDidChangeNotification, 一直有一些问题就是,如果使用这个通知,当i ...

  5. PHP Web木马扫描器代码

    <?php header('content-type:text/html;charset=gbk'); set_time_limit(0);//防止超时 /** * * php目录扫描监控增强版 ...

  6. wepy小程序实现列表分页上拉加载(1)

    使用wepy开发微信小程序商城第一篇:项目初始化 使用wepy开发微信小程序商城第二篇:路由配置和页面结构 列表页效果图: 1.新建列表页 (1)在pages里面新建一个list.wpy文件 初始代码 ...

  7. [Preact] Use State and Props in the Component Render Function

    Preact offers, in addition to the regular component API from React, the ability to access both props ...

  8. HDU 1284 钱币兑换问题 母函数、DP

    题目链接:HDU 1284 钱币兑换问题 钱币兑换问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (J ...

  9. Spring boot(二) springboot + jsp

    官方不推荐JSP在Spring Boot中使用! 一.添加依赖 在pim.xml 里面添加以下 jsp依赖 <dependency> <groupId>org.springfr ...

  10. [Angular] How to styling ng-content

    Let's say you are builing a reuseable component. The style structure like this: div > input If yo ...