思路:

首先令 \(nxt1_i\) 表示右侧最近的城市距离(\(id1_i\) 为编号),令 \(nxt2_i\) 表示右侧第二近的城市编号(\(id2_i\) 为编号);可以使用 set 找出离这个城市最近的 \(4\) 个城市(前面两个,后面两个)。

定义:

  • \(f_{i,j}\) 表示从 \(i\) 点出发走 \(2^j\) 轮最后到达的位置。

  • \(dp1_{i,j}\) 表示从 \(i\) 点出发走 \(2^j\) 轮最后 A 走过的距离。

  • \(dp2_{i,j}\) 表示从 \(i\) 点出发走 \(2^j\) 轮最后 B 走过的距离。

初始化:

\[f_{i,0} = id1_{id2_i}
\]
\[dp1_{i,0} = nxt2_{i}
\]
\[dp2_{i,0} = nxt1_{id2_i}
\]

状态转移方程为:

\[f_{i,j} = f_{f_{i,j-1},j-1}
\]
\[dp1_{i,j} = dp1_{i,j-1} + dp1_{f_{i,j-1},j-1}
\]
\[dp2_{i,j} = dp2_{i,j-1} + dp2_{f_{i,j-1},j-1}
\]

此时对于询问 \(1\) 和询问 \(2\):

  • 本质上是求出从每个城市出发后 \(A\) 走的距离与 \(B\) 走的距离。

  • 那么考虑从高位到低位贪心,即设当前跳到了 \(s\) 点,若 \(dp1_{s,i} + dp2_{s,i} \le x\),可以从 \(s\) 跳到 \(f_{s,i}\),需要令 \(x \gets x - (dp1_{s,i} + dp2_{s,i})\),然后继续遍历 \(i-1\) 位。

  • 因为是 A 先开车,所以 A 可能会在最后一轮结束后还能再开上一次,需要特判。

时间复杂度为 \(O((N+Q) \log N)\)。

完整代码:

#include<bits/stdc++.h>
#define Add(x,y) (x+y>=mod)?(x+y-mod):(x+y)
#define lowbit(x) x&(-x)
#define pi pair<ll,ll>
#define pii pair<ll,pair<ll,ll>>
#define iip pair<pair<ll,ll>,ll>
#define ppii pair<pair<ll,ll>,pair<ll,ll>>
#define fi first
#define se second
#define full(l,r,x) for(auto it=l;it!=r;it++) (*it)=x
#define Full(a) memset(a,0,sizeof(a))
#define open(s1,s2) freopen(s1,"r",stdin),freopen(s2,"w",stdout);
using namespace std;
typedef double db;
typedef unsigned long long ull;
typedef long long ll;
bool Begin;
const ll N=1e5+10,M=18,INF=1e18;
inline ll read(){
ll x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-')
f=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
x=(x<<1)+(x<<3)+(c^48);
c=getchar();
}
return x*f;
}
inline void write(ll x){
if(x<0){
putchar('-');
x=-x;
}
if(x>9)
write(x/10);
putchar(x%10+'0');
}
struct Node{
ll a,b;
ll id;
bool operator<(const Node&rhs)const{
if(a!=rhs.a)
return a<rhs.a;
return b<rhs.b;
}
};
ll n,m,s,x,x0,s0,cnt,dis1,dis2,disa,disb;
ll a[N],nxt1[N],nxt2[N],id1[N],id2[N];
ll f[N][M],dp1[N][M],dp2[N][M];
Node h[N];
vector<Node> V;
multiset<Node> S;
void solve(ll s,ll x){
dis1=dis2=0;
for(int i=M-1;i>=0;i--){
if(dp1[s][i]+dp2[s][i]<=x&&f[s][i]){
dis1+=dp1[s][i],dis2+=dp2[s][i];
x-=dp1[s][i]+dp2[s][i];
s=f[s][i];
}
}
if(nxt2[s]<=x)
dis1+=nxt2[s];
}
bool End;
int main(){
n=read();
for(int i=1;i<=n;i++){
a[i]=read();
h[i]={a[i],a[i],i};
}
S.insert({INF,INF,0});
S.insert({INF-1,INF-1,0});
S.insert({-INF,-INF,0});
S.insert({-INF+1,-INF+1,0});
for(int i=n;i>=1;i--){
V.clear();
V.push_back(*--S.lower_bound(h[i]));
V.push_back(*--S.lower_bound(V[0]));
V.push_back(*S.upper_bound(h[i]));
V.push_back(*S.upper_bound(V[2]));
for(auto &v:V)
v.a=abs(h[i].a-v.a);
sort(V.begin(),V.end());
nxt1[i]=V[0].a,nxt2[i]=V[1].a;
id1[i]=V[0].id,id2[i]=V[1].id;
cerr<<id1[i]<<' '<<id2[i]<<'\n';
S.insert(h[i]);
}
for(int i=1;i<=n;i++){
f[i][0]=id1[id2[i]];
dp1[i][0]=nxt2[i];
dp2[i][0]=nxt1[id2[i]];
}
for(int j=1;j<M;j++){
for(int i=n;i>=1;i--){
f[i][j]=f[f[i][j-1]][j-1];
dp1[i][j]=dp1[i][j-1]+dp1[f[i][j-1]][j-1];
dp2[i][j]=dp2[i][j-1]+dp2[f[i][j-1]][j-1];
}
}
x0=read();
for(int i=1;i<=n;i++){
solve(i,x0);
if(dis2&&(!s0||disa*dis2>disb*dis1)){
s0=i;
disa=dis1,disb=dis2;
}
}
write(s0);
putchar('\n');
m=read();
while(m--){
s=read(),x=read();
solve(s,x);
write(dis1);
putchar(' ');
write(dis2);
putchar('\n');
}
cerr<<'\n'<<abs(&Begin-&End)/1048576<<"MB";
return 0;
}

P1081 [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. NOIP2012 提高组 Day 1

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

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

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

  8. [NOIP2012] 提高组 洛谷P1080 国王游戏

    题目描述 恰逢 H 国国庆,国王邀请 n 位大臣来玩一个有奖游戏.首先,他让每个大臣在左.右 手上面分别写下一个整数,国王自己也在左.右手上各写一个整数.然后,让这 n 位大臣排 成一排,国王站在队伍 ...

  9. [NOIP2012] 提高组 洛谷P1083 借教室

    题目描述 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海量租借教室的信息,我们自然 ...

  10. [NOIP2012] 提高组 洛谷P1082 同余方程

    题目描述 求关于 x 的同余方程 ax ≡ 1 (mod b)的最小正整数解. 输入输出格式 输入格式: 输入只有一行,包含两个正整数 a, b,用一个空格隔开. 输出格式: 输出只有一行,包含一个正 ...

随机推荐

  1. vsftp配置使用

    vsftp简介: VSFTP是一个基于GPL发布的类Unix系统上使用的FTP服务器软件,它的全称是Very Secure FTP 从此名称可以看出来,编制者的初衷是代码的安全. 安全性是编写VSFT ...

  2. centos6 chkconfig的原理 和添加开机自启动的办法

    当我们使用 chkconfig --list的时候 都会又 123456 这样的级别. 当某个级别是 on 他就会开机启动,当他是off 的时候他就不会开机自启动. 那么这是什么原因呢?他的 原理是什 ...

  3. Java中将jsonArray导出为Excel

        java中使用jxl导出excel时,需指定WritableSheet对象中对应于每个单元格的数据.List类型是一种常用的数据类型,它里面的元素是实体对象,当将它创建为WritableShe ...

  4. Windows下cmd命令行sftp上传至Linux服务器

    1.Windows+R进入运行 2.输入cmd,进入命令行 3.命令建立连接 sftp 用户名@ip地址 例如: 输入密码,即可建立连接 上传方式: 1)直接拖动文件到命令行窗口,可以直接显示该文件的 ...

  5. 铭瑄B760 ITX 无法睿频 无法跑满

    铭瑄B760 ITX 无法睿频 无法跑满 状况: 铭瑄B760 ITX + 12600K,跑分时,大核最高 3.7GHz,电压也不到1V.CPU-Z 跑分才600. 解决方法: 1.关机. 2.长按 ...

  6. AIGC底层技术介绍

    1.AIGC概述 AIGC,全称Artificial Intelligence Generated Content,即人工智能生成内容.这是一种新兴的人工智能技术,其核心思想是利用人工智能模型,根据给 ...

  7. PI规划会,研发团队价值聚焦的一剂良方

    随着数字化建设如火如荼地推进,中大型企业的数字化建设团队规模也越来越大,团队规模的扩大一方面带来了更多产能与可能性,另一方面,不同的角色在不同的业务场景也带来了一些现实问题,例如: 作为CIO 或产品 ...

  8. apollo配置中心从数据库中查询所有的配置及项目

    apollo配置中心从数据库中查询所有的配置及项目 需求背景:如果需要从Apollo查询某个配置项做批量的更新替换,如果一个一个找不合适且容易遗漏,需要从底层数据库表中模糊查询来实现. 1.查看apo ...

  9. ThreadLocal 核心源码分析

    ThreadLocal 简介 多线程访问同一个共享变量的时候容易出现并发问题,特别是多个线程对一个变量进行写入的时候,为了保证线程安全,一般使用者在访问共享变量的时候需要进行额外的同步措施才能保证线程 ...

  10. 高通lk:配置与使用i2c

    高通lk:配置与使用i2c 以msm8909为例. 背景 在lk中要去驱动一个aw9523的ic来控制指示灯. 但是现在对应的i2c没有打开.因此需要进行处理. 步骤 找到I2C对应的ID与句柄 参考 ...