其实就是个大模拟。

首先,根据题意,小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. JSON Template

    public java.lang.String toString() {#if ( $members.size() > 0 ) #set ( $i = 0 )return "{\&qu ...

  2. Linux桌面环境

    早期的 Linux 系统都是不带界面的,只能通过命令来管理,比如运行程序.编辑文档.删除文件等.所以,要想熟练使用 Linux,就必须记忆很多命令. 后来随着 Windows 的普及,计算机界面变得越 ...

  3. 小程序报错 “渲染层错误” Expect END descriptor with depth 0 but get another

    项目中有几个页面在控制台出现这个“渲染层错误”,虽然不影响业务操作,怕存在潜在风险,今天抽时间找了下原因,解决这个问题. 控制台报错日志如下: (中国标准时间) 渲染层错误 Error: Expect ...

  4. Docker 一步搞定 ZooKeeper 集群的搭建

    Docker 一步搞定 ZooKeeper 集群的搭建 背景 原来学习 ZK 时, 我是在本地搭建的伪集群, 虽然说使用起来没有什么问题, 但是总感觉部署起来有点麻烦. 刚好我发现了 ZK 已经有了 ...

  5. 使用benchmarkSQL测试数据库的TPCC

    压力测试是指在MySQL上线前,需要进行大量的压力测试,从而达到交付的标准.压力测试不仅可以测试MySQL服务的稳定性,还可以测试出MySQL和系统的瓶颈. TPCC测试:Transaction Pr ...

  6. C++分治策略实现线性时间选择

    问题描述: 给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k小的元素,即如果将这n个元素依其线性序排列时,排在第k个的元素即为要找到元素. 细节须知:(与之前的随笔相比) (1 ...

  7. go 学习笔记---chan

    如果说 goroutine 是 Go语言程序的并发体的话,那么 channels 就是它们之间的通信机制.一个 channels 是一个通信机制,它可以让一个 goroutine 通过它给另一个 go ...

  8. BUAA-OO-2019 第一单元总结

    第一次作业 第一次作业需要完成的任务为简单多项式导函数的求解. 思路 因为仅仅是简单多项式的求导,所以求导本身没有什么可说的,直接套用幂函数的求导公式就行了,主要的精力是花在了正则表达式上.这里推荐两 ...

  9. springboot脚手架liugh-parent源码研究参考

    1. liugh-parent源码研究参考 1.1. 前言 这也是个开源的springboot脚手架项目,这里研究记录一些该框架写的比较好的代码段和功能 脚手架地址 1.2. 功能 1.2.1. 当前 ...

  10. expor和import的用法

    1.Export 模块是独立的文件,该文件内部的所有的变量外部都无法获取.如果希望获取某个变量,必须通过export输出 // profile.js export var firstName = 'M ...