【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 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散 ...
随机推荐
- spring使用context:property-placeholder载不进属性问题 wangbiglei 发表于1年前 原 spring使用context:property-placeholder载不进属性问题
https://my.oschina.net/wangbiglei/blog/489583 http://www.cnblogs.com/leftthen/p/5615066.html
- 关于http请求指定本地ip
static void Main(string[] args) { //ssl证书验证问题(没有校验) ServicePointManager.ServerCertificateValidationC ...
- Socket 长连接与短连接,心跳
长连接与短连接 所谓长连接,指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接,一般需要自己做在线维持. 短连接是指通信双方有数据交互时 ...
- CSS笔记 - fgm练习 2-7 - 简易选项卡
练习地址 http://www.fgm.cc/learn/lesson2/07.html <style> body,ul,li{margin:0;padding:0;} body{font ...
- postman--下载及使用入门
安装 本文只是基于 Chrome 浏览器的扩展插件来进行的安装,并非单独应用程序. 首先,你要台电脑,其次,安装有 Chrome 浏览器,那你接着往下看吧. 1. 官网安装(别看) 打开官网,http ...
- .netcore下的微服务、容器、运维、自动化发布
原文:.netcore下的微服务.容器.运维.自动化发布 微服务 1.1 基本概念 1.1.1 什么是微服务? 微服务架构是SOA思想某一种具体实现.是一种将单应用程序作为一套小型 ...
- 【Educational Codeforces Round 31 A】Book Reading
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 水模拟 [代码] #include <bits/stdc++.h> using namespace std; const ...
- Android开发系列(二十):AutoCompleteTextView(自己主动完毕文本框)的功能和使用方法
当用户输入一定的字符之后,自己主动完毕文本框可以显示一个下拉菜单,供用户从中选择,当用户选择某个菜单项之后,AutoCompleteTextView可以依照用户的选择自己主动填写该文本框 AutoCo ...
- Eclipse "Could not create java virtual machine"的问题解决
今天到了新的环境,需要重新搭建Android的开发环境,下载eclipse并安装了JDK1.6后,启动eclipse,发现出现了错误“Could not create Javavirtual mach ...
- python中如何在一张图上画两条折线
摘自:https://segmentfault.com/q/1010000002760775