正题

题目大意:https://www.luogu.org/problemnew/show/P1081


题目大意

有若干个城市有不同的海拔hhh,两个城市之间的距离定义为∣hx−hy∣|h_x-h_y|∣hx​−hy​∣
小A每次走次近的,小B每次走最近的。它们轮流开车。且只会往编号更大的城市开。
问一:在距离≤X\leq X≤X的情况下求一个起点是的他们两个开的距离之和最小。
问二:若干个Si,XiS_i,X_iSi​,Xi​求在SiS_iSi​出发,距离≤Xi\leq X_i≤Xi​时他们各开多远。


解题思路

首先链表(或平衡树)预处理出gaiga_igai​和gbigb_igbi​表示在第iii个城市小AAA或小BBB下一个会到的城市。

然后考虑dpdpdp
设fi,j,0/1f_{i,j,0/1}fi,j,0/1​表示从jjj出发走了2i2^i2i次,到小A/小B开车,到达的地点。
设dai,j,0/1da_{i,j,0/1}dai,j,0/1​表示从jjj出发走了2i2^i2i次,到小A/小B开车,小AAA走了多远。
设dbi,j,0/1db_{i,j,0/1}dbi,j,0/1​表示从jjj出发走了2i2^i2i次,到小A/小B开车,小BBB走了多远。
然后首先
f0,j,0=gaj,f0,j,1=gbjf_{0,j,0}=ga_j,f_{0,j,1}=gb_jf0,j,0​=gaj​,f0,j,1​=gbj​
da0,j,0=dist(j,gaj),da0,j,1=0da_{0,j,0}=dist(j,ga_{j}),da_{0,j,1}=0da0,j,0​=dist(j,gaj​),da0,j,1​=0
db0,j,1=dist(j,gbj),db0,j,0=0db_{0,j,1}=dist(j,gb_{j}),db_{0,j,0}=0db0,j,1​=dist(j,gbj​),db0,j,0​=0
然后考虑转移
当i=1i=1i=1时
fi,j,k=fi−1,fi−1,j,k,kxor1f_{i,j,k}=f_{i-1,f_{i-1,j,k},k\ xor\ 1}fi,j,k​=fi−1,fi−1,j,k​,k xor 1​
dai,j,k=dai−1,j,k+dai−1,fi−1,j,k,kxor1da_{i,j,k}=da_{i-1,j,k}+da_{i-1,f_{i-1,j,k},k\ xor\ 1}dai,j,k​=dai−1,j,k​+dai−1,fi−1,j,k​,k xor 1​
dbi,j,k=dbi−1,j,k+dbi−1,fi−1,j,k,kxor1db_{i,j,k}=db_{i-1,j,k}+db_{i-1,f_{i-1,j,k},k\ xor\ 1}dbi,j,k​=dbi−1,j,k​+dbi−1,fi−1,j,k​,k xor 1​
但是因为i>1i>1i>1时2i2^i2i依旧是偶数,说以kkk不需要改变
fi,j,k=fi−1,fi−1,j,k,kf_{i,j,k}=f_{i-1,f_{i-1,j,k},k}fi,j,k​=fi−1,fi−1,j,k​,k​
dai,j,k=dai−1,j,k+dai−1,fi−1,j,k,kda_{i,j,k}=da_{i-1,j,k}+da_{i-1,f_{i-1,j,k},k}dai,j,k​=dai−1,j,k​+dai−1,fi−1,j,k​,k​
dbi,j,k=dbi−1,j,k+dbi−1,fi−1,j,k,kdb_{i,j,k}=db_{i-1,j,k}+db_{i-1,f_{i-1,j,k},k}dbi,j,k​=dbi−1,j,k​+dbi−1,fi−1,j,k​,k​

处理好之后,我们定义函数calc(s,x)calc(s,x)calc(s,x)表示
从sss出发,且距离不超过xxx时小AAA和小BBB的行驶距离。

首先我们要设定now,la,lbnow,la,lbnow,la,lb表示现在在哪个点和小AAA和小BBB的行驶距离。

然后当la+lb+dai,now,0+dbi,now,0≤xla+lb+da_{i,now,0}+db_{i,now,0}\leq xla+lb+dai,now,0​+dbi,now,0​≤x时就证明可以行走,那就对应修改now,la,lbnow,la,lbnow,la,lb的值。


codecodecode

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<set>
#define ll long long
using namespace std;
const ll N=101000;
struct Node{ll h,id,prev,next;
}l[N];
set<int> BST;
double ans;
ll n,m,mark,la,lb,t;
ll h[N],f[21][N][2],da[21][N][2];
ll ga[N],gb[N],db[21][N][2],pre[N];
bool left(ll x){if(!l[x].prev) return 0;if(!l[x].next) return 1;return l[x].h-l[l[x].prev].h<=l[l[x].next].h-l[x].h;
}
ll cmps(ll a,ll b,ll x){if(!a) return l[b].id;if(!b) return l[a].id;if(l[x].h-l[a].h<=l[b].h-l[x].h) return l[a].id;return l[b].id;
}
bool cmp(Node x,Node y)
{return x.h<y.h;}
void Part1()
{for(ll i=1;i<=n;i++)l[i].h=h[i],l[i].id=i;sort(l+1,l+1+n,cmp);for(ll i=1;i<=n;i++)pre[l[i].id]=i;for(ll i=1;i<=n;i++)l[i].prev=i-1,l[i].next=i+1;l[1].prev=l[n].next=0;for(ll i=1;i<=n;i++){ll j=pre[i];if(left(j)) gb[i]=l[l[j].prev].id,ga[i]=cmps(l[l[j].prev].prev,l[j].next,j);else gb[i]=l[l[j].next].id,ga[i]=cmps(l[j].prev,l[l[j].next].next,j);l[l[j].prev].next=l[j].next;l[l[j].next].prev=l[j].prev;    }
}
ll dist(ll x,ll y)
{return abs(h[x]-h[y]);}
void Part2()
{for(ll j=1;j<=n;j++){if(ga[j]){f[0][j][0]=ga[j];da[0][j][0]=dist(j,ga[j]);db[0][j][0]=0;}if(gb[j]){f[0][j][1]=gb[j];da[0][j][1]=0;db[0][j][1]=dist(j,gb[j]);}}ll L=0;for(ll i=1;i<=t;i++)for(ll j=1;j<=n;j++)for(ll k=0;k<2;k++){if(i==1) L=k^1;else L=k;f[i][j][k]=f[i-1][f[i-1][j][k]][L];da[i][j][k]=da[i-1][j][k]+da[i-1][f[i-1][j][k]][L];db[i][j][k]=db[i-1][j][k]+db[i-1][f[i-1][j][k]][L];}
}
void calc(ll s,ll x)
{ll now=s;la=lb=0;for(ll i=t;i>=0;i--){if(f[i][now][0]&&la+lb+da[i][now][0]+db[i][now][0]<=x){la+=da[i][now][0];lb+=db[i][now][0];now=f[i][now][0];if(!now) break;}}
}
int main()
{scanf("%lld",&n);t=(int)(log(n*1.0)/log(2.0)+0.001);for(ll i=1;i<=n;i++)scanf("%lld",&h[i]);Part1();Part2();ll X;scanf("%lld",&X);ans=2147483647;for(ll i=1;i<=n;i++){calc(i,X);if(lb&&((double)la/lb)<ans) ans=(double)la/lb,mark=i;}printf("%lld\n",mark);scanf("%lld",&m);for(ll i=1;i<=m;i++){ll s;scanf("%lld%lld",&s,&X);calc(s,X);printf("%lld %lld\n",la,lb);}
}

P1081-开车旅行【倍增,链表,dp】相关推荐

  1. P1081 开车旅行 倍增 洛谷

    题目连接 题意 题目已经说的hin明确了. 题解 我们要求出从每个点出发,小A要走的城市和小B要走的城市. 我们把iii以后的所有点的海拔加入到set" role="present ...

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

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

  3. NOIP2012 开车旅行 (倍增)

    题意:一行N个城市,有各自不同的海拔,定义两个城市之间的距离为海拔之差的绝对值,小a和小b轮流开车,开车方向从左往右,小a总是开到第二近的城市,小b开到最近的城市(如有两个城市和当前城市海拔之差相等, ...

  4. 刷题记录(NC16562 开车旅行)(树上倍增)

    NC16562 开车旅行 题目链接 关键点: 1.预处理:将所有点到达另一个点的最短和次短距离先求出 方法:利用set,从最后一个城市开始插入,每次插入到set中,查看左右是否存在有城市(即set是按 ...

  5. NOIP2012提高组 开车旅行 解题报告

    开车旅行 题目描述 样例输入 样例输出 70分算法 暴力预处理出对于每一个点他右边最近.次近的点的编号,对于每一个询问,暴力模拟开车过程即可. 100算法 和上面一样我们得预处理出每一个点最近.次近的 ...

  6. 【YBTOJ】开车旅行

    思路: 先预处理出每个城市出发,小A小B开车到达的下一个城市. 然后倍增优化DP: { f 0 , i , , j = f 0 , f 0 , i , j − 1 , j − 1 d i s 0 , ...

  7. poj 3728 The merchant// lca(倍增实现) + dp || tarjan+并查集路径上dp

    poj 3728 The merchant// lca(倍增实现) + dp Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: ...

  8. NOIP2012 开车旅行

    开车旅行 (drive.cpp/c/pas) [问题描述] 小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度 ...

  9. P1081 [NOIP2012 提高组] 开车旅行(倍增)(动态规划)

    洛谷传送门 文章目录 题目描述 解析 代码 题目描述 解析 利用倍增,设计dp慢慢敲即可... 注意距离累加在一起会爆int,需要ll 特判条件非常之复杂... 心力交瘁,就酱了 代码 #includ ...

最新文章

  1. 利用bind搭建dns
  2. c51单片机汇编语言电梯,C51单片机汇编语言指令集.doc
  3. vue给组件传html,如何将 html 模板作为道具传递给 Vue 组件
  4. 数据库mysql报2005错_sql2005还原数据库错误的问题解决方法
  5. 7人表决器的实现之路
  6. 苹果cms替换资源_苹果cmsV10整合云转码(PPVOD)插件
  7. 小家电企业坐上“过山车”,是谁浇灭了年轻人的热情?
  8. Flex Builder中网络监视器导致“访问URL时遇到安全性错误”
  9. 分享四款实用流程图模板
  10. 带你十分钟做出一个自己的手机APP
  11. C语言算法题:一只小蜜蜂...
  12. 数据治理系列8:数据价值管理
  13. wd 文件服务器客服电话,wd 云服务器
  14. uni-app小程序云开发函数——记录
  15. validform_v5.3.2帮助文档
  16. 最忌讳的18个小动作
  17. Mac下使用Git和Git客户端
  18. 【19调剂】湖南大学信息科学与工程学院2019年硕士研究生调剂通知(校内)
  19. 通过 Windows AIK 创建 Windows RE
  20. nodejs nodemailer 使用

热门文章

  1. mysql左键关联_MySQL的:左键删除重复列加入,3个表
  2. hilbert曲线序编码matlab,Hilbert曲线扫描矩阵的生成算法及其MATLAB程序代码
  3. php引用类,thinkphp引用类的使用
  4. 宝塔部署node项目_宝塔面板部署 node.js 项目
  5. 7-27 家谱处理 (30 分)(详解+map做法)map真香啊
  6. C++ const修饰符的简单介绍
  7. [Java基础]Lambda表达式练习
  8. [蓝桥杯2016决赛]路径之谜
  9. Largest Rectangle in a Histogram (动态规划+奇思妙想单调栈)求最大矩状图面积
  10. c语言表达式5 gt 3 gt 1,C语言题目谁会做?