洛谷P1081 开车旅行(倍增)
题意
Sol
咕了一年的题解。。
并不算是很难,只是代码有点毒瘤
\(f[i][j]\)表示从\(i\)号节点出发走了\(2^j\)轮后总的距离
\(da[i][j]\)同理表示\(a\)的距离,\(db[i][j]\)与\(da\)同理
倍增优化一下
注意最后\(a\)可能还会走一次
#include<bits/stdc++.h>
#define Pair pair<int, int>
#define MP make_pair
#define fi first
#define se second
#define Fin(x) {freopen(#x".in","r",stdin);}
#define pb(x) push_back(x)
#define LL long long
//#define int long long
using namespace std;
const int MAXN = 1e5 + 10;
LL INF = 2e9 + 10, B = 20;
inline int read() {
char c = getchar(); int x = 0, f = 1;
while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
int N, jp[MAXN][21], nxa[MAXN], nxb[MAXN], flag[MAXN], h[MAXN];
LL f[MAXN][21], da[MAXN][21], db[MAXN][21];
struct Node {
LL Hi, id;
bool operator < (const Node &rhs) const{
return Hi == rhs.Hi ? h[id] < h[rhs.id] : Hi < rhs.Hi;
}
};
int get(int x, int y) {
return abs(h[x] - h[y]);
}
set<Node> s;
void Pre() {
s.insert((Node) {-INF * 2, 0}); s.insert((Node) {INF * 2, 0});
s.insert((Node) {-INF * 2 + 1, 0}); s.insert((Node) {INF * 2 + 1, 0});
s.insert((Node) {h[N], N});
memset(f, 0x3f, sizeof(f));
for(int i = N - 1; i >= 1; i--) {
set<Node> :: iterator y = s.lower_bound((Node) {h[i], i});
vector<Node> tmp; tmp.clear();
tmp.push_back((Node) {get(y -> id, i), y -> id}); y++;
tmp.push_back((Node) {get(y -> id, i), y -> id}); y--; y--;
tmp.push_back((Node) {get(y -> id, i), y -> id}); y--;
tmp.push_back((Node) {get(y -> id, i), y -> id});
sort(tmp.begin(), tmp.end());
nxa[i] = tmp[1].id;
nxb[i] = tmp[0].id;
s.insert((Node) {h[i], i});
if(tmp[1].id != 0 && tmp[0].id != 0) f[i][0] = tmp[1].Hi + db[tmp[1].id][0];
jp[i][0] = nxb[nxa[i]];
da[i][0] = get(i, nxa[i]);
db[i][0] = get(i, nxb[i]);
}
for(int j = 1; j <= B; j++)
for(int i = 1; i <= N; i++) {
if(jp[i][j - 1])
jp[i][j] = jp[jp[i][j - 1]][j - 1],
f[i][j] = f[i][j - 1] + f[jp[i][j - 1]][j - 1],
da[i][j] = f[i][j] == INF ? 0 : da[i][j - 1] + da[jp[i][j - 1]][j - 1];
}
}
void print() {
for(int i = 1; i <= N; i++) printf("**%d\n", f[i][0]);
}
Pair Query(int pos, int val) {
LL a1 = 0, a2 = 0;
for(int i = B; ~i; i--)
if(f[pos][i] <= val)
val -= f[pos][i], a1 += da[pos][i], a2 += f[pos][i] - da[pos][i], pos = jp[pos][i];
if(da[pos][0] <= val) a1 += da[pos][0];
return MP(a1, a2);
}
signed main() {
// freopen("drive3.in", "r", stdin);
// freopen("a.out", "w", stdout);
N = read();
for(int i = 1; i <= N; i++) h[i] = read(); h[0] = INF;
Pre();
// print();
int X0 = read(), ans = N;
double tmp = 1e22;
for(int i = 1; i <= N; i++) {
Pair now = Query(i, X0);
if(now.se == 0) continue;
if((double)now.fi / now.se < tmp) tmp = (double)now.fi / now.se, ans = i;
}
printf("%d\n", ans);
int M = read();
while(M--) {
int Si = read(), Mi = read();
Pair now = Query(Si, Mi);
printf("%d %d\n", now.fi, now.se);
}
return 0;
}
洛谷P1081 开车旅行(倍增)的更多相关文章
- 洛谷 P1081 开车旅行 —— 倍增
题目:https://www.luogu.org/problemnew/show/P1081 真是倍增好题! 预处理:f[i][j] 表示从 i 点开始走 2^j 次 AB (A,B各走一次)到达的点 ...
- 洛谷 P1081 开车旅行(70)
P1081 开车旅行 题目描述 小AA 和小BB 决定利用假期外出旅行,他们将想去的城市从 11到 NN 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 ii的海 ...
- 2018.11.04 洛谷P1081 开车旅行(倍增)
传送门 思路简单码量超凡? 感觉看完题大家应该都知道是倍增sbsbsb题了吧. 首先预处理出从每个点出发如果是AAA走到哪个点,如果是BBB走到哪个点. 然后利用刚刚预处理出的信息再预处理从每个点出发 ...
- 洛谷 P1081 开车旅行【双向链表+倍增】
倍增数组的20和N写反了反复WAWAWA-- 注意到a和b在每个点上出发都会到一个指定的点,所以这样构成了两棵以n点为根的树 假设我们建出了这两棵树,对于第一问就可以枚举起点然后倍增的找出ab路径长度 ...
- [NOIP2012] 提高组 洛谷P1081 开车旅行
题目描述 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的 城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为 Hi,城市 ...
- NOIP 2012 洛谷P1081 开车旅行
Description: 就是两个人开车,只能向东开.向东有n个城市,城市之间的距离为他们的高度差.A,B轮流开车,A喜欢到次近的城市,B喜欢到最近的城市.如果车子开到底了或者车子开的路程已经超过了限 ...
- 洛谷P1081 开车旅行
题目 双向链表+倍增+模拟. \(70pts\): 说白了此题的暴力就是细节较多的模拟题. 我们设离\(i\)城市最近的点的位置为\(B[i]\),第二近的位置为\(A[i]\).设\(A\)或\(B ...
- 洛谷P1081——开车旅行
传送门:QAQQAQ 题意注意点: 1.是从前往后走,不能回头 2.小A小B轮流开,先小A开,而小A是到第二近的点(这点调试的时候查了好久) 3.若绝对值差相同海拔低的更近,而第一个询问若比值相同是海 ...
- 洛谷P1081 开车旅行70分
https://www.luogu.org/problem/show?pid=1081 太遗憾了明明写出来了,却把最小值初始值弄小了,从第二个点开始就不可能对了.70分! #include<io ...
随机推荐
- sqlalchemy中使用event设置条件触发短信与邮件通知
一.原因 近期在做短信与邮件通知系统.使用到了这一块.例如,当订单完成以后进行邮件短信的通知.虽然可以采用直接调用接口的方式实现,但有几个原因让我希望使用条件触发的方式 1.由于系统中支持线上线下以及 ...
- 对cors的理解
一.简介 CORS需要浏览器和服务器同时支持.目前,所有浏览器都支持该功能,IE浏览器不能低于IE10. 整个CORS通信过程,都是浏览器自动完成,不需要用户参与.对于开发者来说,CORS通信与同源的 ...
- The score of 'O' and 'X'
题目描述 注意要点: 使用strlen函数注意加头文件#inlcude <cstring> 循环宏定义for循环#define _for(i,a,b) for(int i=(a);i< ...
- HTML DOM--基础概述
DOM: Document Object Model(文档对象模型)的简写,那么,这是一种什么样的模型,简单点来说,就是将文档当成了一棵树.它独立于平台与语言,允许程序与脚本动态地访问.更新文档的结构 ...
- mongodb与python随手记
在python中使用pymongo连接mongodb数据库. 基本代码如下: from pymongo import MongoClient client = MongoClient('127.0.0 ...
- web及时通信传输的几种方法
有哪些: 轮询.长轮询.iframe流.websocket 轮询:http的请求有一个很明显的缺点,就是只能有客户端发起,不能由服务端主动推送,所以轮询就是定时向服务器发送请求,去获取数据 优点:传输 ...
- jsp、Servlet的面试题
3. 谈谈Servlet的生命周期 当接收到请求的时候,容器察看对应的Servlet对象是否存在,如果不存在,需要加载Servetl,实例化Servlet,调用init方法进行初始化.如果已经存在,根 ...
- vue过渡效果
vue过渡效果. <transition name='slide-fade'> <div class="top" @click='gotoTop' v-if='s ...
- [目录]hybrid app 开发实战(基于ionic,cordova,angularjs)
序:为什么要写这个系列 第一章:hybrid app开发之技术选型 第二章:ionic,cordova,phonegap关系浅析 第三章:ionic环境搭建之windows篇 第四章:ionic环境搭 ...
- XmlReader在序列化中的使用
和XmlDocument最大的不同——XmlReader逐行读取.单独很少使用,一般配合序列化(反序列化)使用,以下给出具体例子: namespace ConsoleApplication1 { pu ...