Loj2604开车旅行

我完全没有看出这道题哪里是DP

首先,一个位置向后的最近和第二近我们可以通过set去简单实现

通过维护最大和次大即可

至于高度相同的情况我们可以通过先在set中查询小的来实现

接下来我们考虑倍增

\(f_{i,j}\)表示从位置\(j\)开始向后开\(2^i\)次所到达的位置(这里一次的定义是小A走一次然后小B再走一次)

我们设\(g1_{i,j}\)表示从\(j\)开始向后走\(2^i\)步的过程中小A走的路程,\(g2_{i,j}\)表示小B的

我们每次对于一个\(s_i,x_i\)我们尝试在\(s_i\)位置倍增向后跳,跳到马上大于\(x_i\)或者无路可走位置

如果无路可走,说明剩下的路程不满足走一次,但是可能出现小A还能走得情况,所以要特判

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cctype>
#include<set>
#include<queue>
#include<cmath>
#include<algorithm>
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
#define LL long long
using namespace std;
const int N = 2e5 + 3;
const int INF = 2e9;
int n,m;
int h[N];
pii nxt1[N],nxt2[N];
int f[21][N];
LL g1[21][N],g2[21][N];
set < pii > s;
set < pii >::iterator it;
inline int read(){
int v = 0,c = 1;char ch = getchar();
while(!isdigit(ch)){
if(ch == '-') c = -1;
ch = getchar();
}
while(isdigit(ch)){
v = v * 10 + ch - 48;
ch = getchar();
}
return v * c;
}
int main(){
n = read();
for(int i = 1;i <= n;++i) h[i] = read();
for(int i = n;i >= 1;--i){
pii f1 = mk(INF,0),f2 = mk(INF,0);LL v = 0;
it = s.lower_bound(mk(h[i],i));
if(it != s.begin()){
it--;
v = abs((*it).fi - h[i]);
if(v < f1.fi) f2 = f1,f1 = mk(v,(*it).se);
else if(v < f2.fi) f2 = mk(v,(*it).se);
if(it != s.begin()){
it--;
v = abs((*it).fi - h[i]);
if(v < f1.fi) f2 = f1,f1 = mk(v,(*it).se);
else if(v < f2.fi) f2 = mk(v,(*it).se);
}
}
it = s.upper_bound(mk(h[i],i));
if(it != s.end()){
v = abs((*it).fi - h[i]);
if(v < f1.fi) f2 = f1,f1 = mk(v,(*it).se);
else if(v < f2.fi) f2 = mk(v,(*it).se);
it++;
if(it != s.end()){
v = abs((*it).fi - h[i]);
if(abs((*it).fi - h[i]) < f1.fi) f2 = f1,f1 = mk(v,(*it).se);
else if(v < f2.fi) f2 = mk(v,(*it).se);
}
}
if(f1.se) nxt1[i] = f1;
if(f2.se) nxt2[i] = f2;
s.insert(mk(h[i],i));
}
for(int i = 1;i <= n;++i){
// printf("1s:%d 1id:%d 2s:%d 2id:%d\n",nxt1[i].fi,nxt1[i].se,nxt2[i].fi,nxt2[i].se);
f[0][i] = nxt1[nxt2[i].se].se;
g1[0][i] = nxt2[i].fi;
g2[0][i] = nxt1[nxt2[i].se].fi;
// printf("%d %lld %lld\n",f[0][i],g1[0][i],g2[0][i]);
}
for(int i = 1;i < 20;++i){
for(int j = 1;j <= n;++j){
f[i][j] = f[i - 1][f[i - 1][j]];
if(f[i][j]){
g1[i][j] = g1[i - 1][j] + g1[i - 1][f[i - 1][j]];
g2[i][j] = g2[i - 1][j] + g2[i - 1][f[i - 1][j]];
}
}
}
// printf("%d %lld %lld\n",f[1][1],g1[1][1],g2[1][1]);
LL x0 = read();int maxxhi = 0,id = 0;LL zi = 0,mu = 0;
for(int i = 1;i <= n;++i){
LL z1 = 0,m1 = 0,tt = 0;int x = i;
for(int j = 19;j >= 0;--j){
if(f[j][x]){
if(tt + g1[j][x] + g2[j][x] <= x0){
tt += g1[j][x] + g2[j][x];
z1 += g1[j][x],m1 += g2[j][x],x = f[j][x];
}
}
}
if(nxt2[x].se && tt + nxt2[x].fi <= x0) tt += nxt2[x].fi,z1 += nxt2[x].fi;
if(m1 == 0){
if(mu != 0) continue;
if(maxxhi < h[i]) zi = z1,mu = m1,maxxhi = h[i],id = i;
}
else{
if(mu == 0){
zi = z1,mu = m1,maxxhi = h[i],id = i;
continue;
}
if(z1 * mu < zi * m1) zi = z1,mu = m1,maxxhi = h[i],id = i;
else if(z1 * mu == zi * m1 && maxxhi < h[i]) zi = z1,mu = m1,maxxhi = h[i],id = i;
}
}
printf("%d\n",id);
m = read();
while(m--){
int si = read(),xi = read();
LL s1 = 0,s2 = 0;int x = si;LL tt = 0;
for(int j = 19;j >= 0;--j){
if(f[j][x]){
if(tt + g1[j][x] + g2[j][x] <= xi){
tt += g1[j][x] + g2[j][x];
s1 += g1[j][x],s2 += g2[j][x],x = f[j][x];
}
}
}
if(nxt2[x].se && tt + nxt2[x].fi <= xi) s1 += nxt2[x].fi;
printf("%lld %lld\n",s1,s2);
}
return 0;
}

Loj2604开车旅行的更多相关文章

  1. Luogu 1081 【NOIP2012】开车旅行 (链表,倍增)

    Luogu 1081 [NOIP2012]开车旅行 (链表,倍增) Description 小A 和小B决定利用假期外出旅行,他们将想去的城市从1到N 编号,且编号较小的城市在编号较大的城市的西边,已 ...

  2. CH5701 开车旅行

    题意 5701 开车旅行 0x50「动态规划」例题 描述 小A和小B决定利用假期外出旅行,他们将想去的城市从1到N编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 ...

  3. 2012Noip提高组Day1 T3 开车旅行

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

  4. Cogs 1264. [NOIP2012] 开车旅行(70分 暴力)

    1264. [NOIP2012] 开车旅行 ★★☆   输入文件:drive.in   输出文件:drive.out   简单对比时间限制:2 s   内存限制:128 MB [题目描述] 小A 和小 ...

  5. 开车旅行 【NOIP2012 D1T3】

    开车旅行 [NOIP2012 D1T3] 倍增 首先令\(a[i]\)表示从i出发最近的城市下标,\(b[i]\)表示从i出发第二近的城市下标 可以维护一个\(\text{set<pair< ...

  6. 洛谷 P1081 开车旅行(70)

    P1081 开车旅行 题目描述 小AA 和小BB 决定利用假期外出旅行,他们将想去的城市从 11到 NN 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 ii的海 ...

  7. 开车旅行 2012年NOIP全国联赛提高组(倍增+set)

    开车旅行 2012年NOIP全国联赛提高组  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond     题目描述 Description 小A 和小B决定利用 ...

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

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

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

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

随机推荐

  1. iOS 获取 APP 的 Launch Image

    http://www.cocoachina.com/ios/20151027/13780.html 作者:里脊串 授权本站转载. 启动图(LaunchImage)的管理其实在iOS开始中算比较简单的了 ...

  2. pl/sql基础知识—触发器

    n  触发器简单介绍 触发器是指隐含执行的存储过程,它不是由程序员或者是DBA来显式调用,而是因为某个操作引发执行的.当定义触发器时,必须要指定触法的事件和触发的操作,常用的触发事件包括insert, ...

  3. 写一个nginx监控日志

    下面的代码是实现一个nginx监控日志功能,是不是很好玩呢.

  4. python 顺序传入

  5. [CS]C#操作word 2016-04-17 18:30 1506人阅读 评论(35) 收藏

    最近在做的项目已经改了好几版,最近这一版用到了word,当然不是直接使用word,而是使用第三方的ActiveX控件:dsoframer.ocx,此控件的使用和其他控件的使用流程没有任何区别,接下来介 ...

  6. Spark in action on Kubernetes - 存储篇(一)

    前言 在上篇文章中,我们分析了Spark Operator内部的机制,今天我们会讨论一个在大数据领域中最重要的话题 - 存储.大数据已经无声无息的融入了每个人的生活中.大到旅游买房,小到外卖打车,都可 ...

  7. HZOJ 连连看

    考场几乎想到了正解,然而我也不知道当时在想啥,在没有证伪的情况下只是觉得无法实现就否了…… 最后打的好象是达哥说的O(4*15*n*m),复杂度不是很会证反正T成了暴力…… 题解: 对于测试点8,9, ...

  8. python环境测试MySQLdb、DBUtil、sqlobject性能

    python环境测试MySQLdb.DBUtil.sqlobject性能 首先介绍下MySQLdb.DBUtil.sqlobject: (1)MySQLdb 是用于Python连接Mysql数据库的接 ...

  9. BUAA 169 电话费

    http://oj55.bianchengla.com/problem/169/ 还有这个,不怎么好做,最后用栈做出来了. 感觉比较有用的一个数据是: 10 3 1010101010 代码如下: #i ...

  10. Where是深复制

    从一个List中通过Where过滤出来的子List或Fist出来的单独元素,与原List是深复制关系.也就是说修改子list,或单独元素,并不会影响原List中的对象. 如:Geom g = Geom ...