其实就是个大模拟。

首先,根据题意,小A和小B从任意一个城市开始走,无论\(X\)如何,其路径是一定唯一的。

显然对于两问都可以想出一个\(O(n^2)\)的暴力,即直接一步一步地向右走。

首先,我们当然需要知道A,B在每个城市的下一步如何走,记\(nexta(i),nextb(i)\)为A,B在\(i\)处时,下一步走到的城市编号。

考虑如何高效(复杂度小于等于\(O(nlogn)\))维护两个\(next\)。

显然不能直接维护每个城市与其后面的城市的差值,再好的数据结构也会到\(O(n^2)\)。

不妨考虑从后往前依次插入\(H_i\),然后动态维护\(H_i\sim H_n\)的有序集合。这样的话,在有序集合中,最小的差值一定要么是\(H_i\)与其前驱,要么就是与其后继的差值。次小的差值,就是\(H_i\)前驱、前驱的前驱、后继、后继的后继与\(H_i\)的差值的次小值。这个问题,平衡树解决之,预处理\(O(nlogn)\)。

下面考虑走\(k\)步的情况,当前步是A走还是B走与步数的奇偶性有关,因此我们还要分开讨论。

那么,我们不妨考虑以此为基础进行优化,比如优化到\(O(nlogn)\)。显然地,对于这样的问题,我们可以倍增预处理,\(O(logn)\)询问。

接下来考察我们需要什么信息,分别是\(i\)向后走\(k\)步的城市,A和B从\(i\)向后走\(k\)步的路程。

设\(f[0/1][i][j]\)为从\(i\)位置,0A,1B向后走\(2^j\)步的城市。

显然

\[f[0][i][0]=nexta(i)\\f[1][i][0]=nextb(i)
\]

由于,走\(2^0\)步是走奇数步,有转移

\[f[0][i][1]=f[1][f[0][i][0]][0]\\f[1][i][1]=f[0][f[1][i][0]][0]
\]

对于走\(2^j\)步,有

\[f[0][i][j]=f[0][f[0][i][j-1]][j-1]\\f[1][i][j]=f[1][f[1][i][j-1]][j-1]
\]

设\(da[0/1][i][j]\)表示从\(i\)位置,A向后走\(2^j\)步的路程,且现在(当前步)是0A,1B在开车,还没走时的A开的距离

显然

\[da[0][i][0]=dist(i,nexta(i))\\da[1][i][0]=0
\]

有转移

\[da[0][i][1]=da[0][i][0]+da[1][f[0][i][0]][0]\\da[1][i][1]=da[1][i][0]+da[0][f[1][i][0]][0]\\da[0][i][j]=da[0][i][j-1]+da[0][f[0][i][j-1]][j-1]\\da[1][i][j]=da[1][i][j-1]+da[1][f[1][i][j-1]][j-1]
\]

设\(db[0/1][i][j]\)表示从\(i\)位置,B向后走\(2^j\)步的路程,且现在是0A,1B在开车。

跟\(da\)差别不大,不再赘述。

预处理完成之后,我们开始考虑题述问题。

对于第一问,对给出的\(X_0\),我们枚举城市\(S_i\),倍增统计走\(X_0\)步的答案(当然超出\(N\)要特判),\(O(nlogn)\)解决之。

对于第二问,同样的,对于每一组\(S_i,X_i\),直接倍增统计即可,复杂度\(O(mlogn)\)。

总复杂度在\(O((n+m)logn)\)左右,完全可以通过本题。

注意,这道题的细节之数量足以让人去世。

代码未经重构,很丑。

参考代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<set>
#include<map>
#include<vector>
#define INF 0x7fffffff
#define PI acos(-1.0)
#define N 100010
#define MOD 2520
#define E 1e-12
#define ll long long
using namespace std;
inline ll read()
{
ll f=1,x=0;char c=getchar();
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;
}
set<int> h;
map<int,int> mp;
int t;
ll n,a[N],na[N],nb[N],f[2][N][21],da[2][N][21],db[2][N][21];
int main()
{
n=read();t=log2(n);
for(int i=1;i<=n;++i) a[i]=read();
a[0]=INF,a[n+1]=-INF;
h.insert(INF);
h.insert(-INF);
mp[-INF]=0,mp[INF]=n+1;
for(int i=n;i>=1;--i){
h.insert(a[i]);mp[a[i]]=i;
ll n1=((++h.find(a[i])!=h.end())?(*++h.find(a[i])):INF),n2=(((++(++h.find(a[i])))!=h.end())?(*++(++h.find(a[i]))):INF);
ll p1=((h.find(a[i])!=h.begin())?(*--h.find(a[i])):-INF),p2=((--h.find(a[i])!=h.end())?(*--(--h.find(a[i]))):-INF);
if(n1-a[i]>=a[i]-p1){
nb[i]=mp[p1];
na[i]=(n1-a[i]>=a[i]-p2)?mp[p2]:mp[n1];
}
else{
nb[i]=mp[n1];
na[i]=(n2-a[i]>=a[i]-p1)?mp[p1]:mp[n2];
}
f[0][i][0]=na[i];f[1][i][0]=nb[i];
da[0][i][0]=abs(a[i]-a[na[i]]);
db[1][i][0]=abs(a[i]-a[nb[i]]);
}
for(int j=1;j<=t;++j){
for(int i=1;i<=n;++i){
if(j==1){
f[0][i][1]=f[1][f[0][i][0]][0];
f[1][i][1]=f[0][f[1][i][0]][0];
da[0][i][1]=da[0][i][0]+da[1][f[0][i][0]][0];
da[1][i][1]=da[1][i][0]+da[0][f[1][i][0]][0];
db[0][i][1]=db[0][i][0]+db[1][f[0][i][0]][0];
db[1][i][1]=db[1][i][0]+db[0][f[1][i][0]][0];
}else{
f[0][i][j]=f[0][f[0][i][j-1]][j-1];
f[1][i][j]=f[1][f[1][i][j-1]][j-1];
da[0][i][j]=da[0][i][j-1]+da[0][f[0][i][j-1]][j-1];
da[1][i][j]=da[1][i][j-1]+da[1][f[1][i][j-1]][j-1];
db[0][i][j]=db[0][i][j-1]+db[0][f[0][i][j-1]][j-1];
db[1][i][j]=db[1][i][j-1]+db[1][f[1][i][j-1]][j-1];
}
}
}/
int x0=read(),s0=0;
double ans=1e14,nans=1e14;//task 1
for(int i=1;i<=n;++i){
int now=i;
ll resa=0,resb=0;
for(int j=t;j>=0;--j){
if(f[0][now][j]){
if(resa+resb+da[0][now][j]+db[0][now][j]>x0)
continue;
resa+=da[0][now][j];resb+=db[0][now][j];
now=f[0][now][j];
}
}
nans=(double)resa/(double)resb;
if(nans<ans){
ans=nans,s0=i;
}
else{
if(nans==ans&&a[s0]<a[i]) s0=i;
}
}
printf("%d\n",s0);
int m=read();//task 2
while(m--){
ll si=read(),xi=read();
ll resa=0,resb=0,now=si;
for(int j=t;j>=0;--j){
if(f[0][now][j]){
if(resa+resb+da[0][now][j]+db[0][now][j]>xi)
continue;
resa+=da[0][now][j];resb+=db[0][now][j];
now=f[0][now][j];
}
}
printf("%lld %lld\n",resa,resb);
}
return 0;
}

P1081 开车旅行[倍增](毒瘤题)的更多相关文章

  1. 洛谷 P1081 开车旅行 —— 倍增

    题目:https://www.luogu.org/problemnew/show/P1081 真是倍增好题! 预处理:f[i][j] 表示从 i 点开始走 2^j 次 AB (A,B各走一次)到达的点 ...

  2. 洛谷P1081 开车旅行(倍增)

    题意 题目链接 Sol 咕了一年的题解.. 并不算是很难,只是代码有点毒瘤 \(f[i][j]\)表示从\(i\)号节点出发走了\(2^j\)轮后总的距离 \(da[i][j]\)同理表示\(a\)的 ...

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

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

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

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

  5. 2018.11.04 洛谷P1081 开车旅行(倍增)

    传送门 思路简单码量超凡? 感觉看完题大家应该都知道是倍增sbsbsb题了吧. 首先预处理出从每个点出发如果是AAA走到哪个点,如果是BBB走到哪个点. 然后利用刚刚预处理出的信息再预处理从每个点出发 ...

  6. 洛谷 P1081 开车旅行【双向链表+倍增】

    倍增数组的20和N写反了反复WAWAWA-- 注意到a和b在每个点上出发都会到一个指定的点,所以这样构成了两棵以n点为根的树 假设我们建出了这两棵树,对于第一问就可以枚举起点然后倍增的找出ab路径长度 ...

  7. [NOIP2012] 提高组 洛谷P1081 开车旅行

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

  8. P1081 开车旅行

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

  9. 【vijos1780】【NOIP2012】开车旅行 倍增

    题目描述 有\(n\)个城市,第\(i\)个城市的海拔为\(h_i\)且这\(n\)个城市的海拔互不相同.编号比较大的城市在东边.两个城市\(i,j\)之间的距离为\(|h_i-h_j|\) 小A和小 ...

随机推荐

  1. cad.net GeometricExtents出错了 调试看不到文字

     飞诗: 难道块不能取GeometricExtents   GeometryExtentsBestFit 用这个解决    GeometryExtentsBestFit 对动态块也不准   com方式 ...

  2. Python 中如何判断 list 中是否包含某个元素

    在python中判断 list 中是否包含某个元素: ——可以通过in和not in关键字来判读 例如: abcList=['a','b','c',1,2,3] if 'a' in abcList: ...

  3. CloseableHttpClient方式配置代理服务器访问外网

    小编最近在负责银行内部项目.其中有模块需要访问天眼查API接口,但由于公司全部内网,所以需要配置代理服务器才可以访问外网接口. 又到了激动人心的上码时刻! public void Connect(Ht ...

  4. Java核心技术 卷一(序言+0-5)

    l 常见简写: JDK(Java Development Kit):Java开发工具包 API:应用程序编程接口 OOP(Object-Oriented Programming):面向对象程序设计 l ...

  5. GIT 安装和使用

    目录 GIT 安装和使用 一.GIT 介绍 二.GIT 安装 三.GIT 使用 1. 配置 2. 创建版本库 3. 远程仓库 4. 分支管理 5.标签管理 6. 自定义 GIT 安装和使用 一.GIT ...

  6. SQL系列(九)—— 子查询(subQuery)

    1.子查询 前面的系列介绍的都是简单的查询场景,其中都只涉及到单张表的数据检索.但是在日常是实际应用中,数据模型之间的关系都非常的复杂,数据的需求一般都是来源于多个数据模型之间的组合而成,即对应多张表 ...

  7. 什么是k8s

    •Kubernetes介绍 1.背景介绍 云计算飞速发展 - IaaS - PaaS - SaaS Docker技术突飞猛进 - 一次构建,到处运行 - 容器的快速轻量 - 完整的生态环境 2.什么是 ...

  8. 封装:Windows系统文件图标

    原文:封装:Windows系统文件图标 用途:用于获取文件系统默认图标 using System; using System.Collections.Generic; using System.Dra ...

  9. 使用php函数防止SQL注入方法

    什么是SQL注入? SQL注入是指在你系统防御之外,某人将一段Mysql语句注入到你的数据库.注入通常发生在系统要求用户输入数据的时候,比如用户名的输入,用户可能输入的不是一个用户名,而是一段SQL语 ...

  10. SQL根据指定节点ID获取所有父级节点和子级节点

    --根据指定节点ID获取所有子节点-- WITH TEMP AS ( SELECT * FROM table_name WHERE Id=' --表的主键ID UNION ALL SELECT T0. ...