【问题描述】
小 A 和小 B 决定利用假期外出旅行,他们将想去的城市从 1 到 N 编号,且编号较小的
城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市 i 的海拔高度为
H i ,城市 i 和城市 j 之间的距离 d[i,j]恰好是这两个城市海拔高度之差的绝对值,即
d[i, j] = |H i − H j |。
旅行过程中,小 A 和小 B 轮流开车,第一天小 A 开车,之后每天轮换一次。他们计划
选择一个城市 S 作为起点,一直向东行驶,并且最多行驶 X 公里就结束旅行。小 A 和小 B
的驾驶风格不同,小 B 总是沿着前进方向选择一个最近的城市作为目的地,而小 A 总是沿
着前进方向选择第二近的城市作为目的地(注意:本题中如果当前城市到两个城市的距离
相同,则认为离海拔低的那个城市更近)。如果其中任何一人无法按照自己的原则选择目的
城市,或者到达目的地会使行驶的总距离超出 X 公里,他们就会结束旅行。
在启程之前,小 A 想知道两个问题:
1.对于一个给定的 X=X 0 ,从哪一个城市出发,小 A 开车行驶的路程总数与小 B 行驶
的路程总数的比值最小(如果小 B 的行驶路程为 0,此时的比值可视为无穷大,且两个无穷大视为相等)。如果从多个城市出发,小 A 开车行驶的路程总数与小 B 行驶的路程总数的比值都最小,则输出海拔最高的那个城市。
2. 对任意给定的 X=X i 和出发城市 S i ,小 A 开车行驶的路程总数以及小 B 行驶的路程总数。
【输入】
输入文件为 drive.in。
第一行包含一个整数 N,表示城市的数目。
第二行有 N 个整数,每两个整数之间用一个空格隔开,依次表示城市 1 到城市 N 的海拔高度,即 H 1 ,H 2 ,......,H n ,且每个 H i 都是不同的。
第三行包含一个整数 X 0 。
第四行为一个整数 M,表示给定 M 组 S i 和 X i 。
接下来的 M 行,每行包含 2 个整数 S i 和 X i ,表示从城市 S i 出发,最多行驶 X i 公里。
【输出】
输出文件为 drive.out。
输出共 M+1 行。
第一行包含一个整数 S 0 ,表示对于给定的 X 0 ,从编号为 S 0 的城市出发,小 A 开车行驶的路程总数与小 B 行驶的路程总数的比值最小。
接下来的 M 行,每行包含 2 个整数,之间用一个空格隔开,依次表示在给定的 S i 和X i 下小 A 行驶的里程总数和小 B 行驶的里程总数。
【数据范围】
对于 30%的数据,有 1≤N≤20,1≤M≤20;
对于 40%的数据,有 1≤N≤100,1≤M≤100;
对于 50%的数据,有 1≤N≤100,1≤M≤1,000;
对于 70%的数据,有 1≤N≤1,000,1≤M≤10,000;
对于 100%的数据,有 1≤N≤100,000,1≤M≤10,000,-1,000,000,000≤H i ≤1,000,000,000,0≤X 0 ≤1,000,000,000,1≤S i ≤N,0≤X i ≤1,000,000,000,数据保证 H i 互不相同。

正解:倍增+set

解题报告:

  显然要先预处理再查找。我的做法就是先用set维护距离每个点的最近点和次近点,讨论比较复杂。。。错了几发,需要了考虑有可能最近点和次近点都是由同一个大小关系转移过来,而且相等的时候,小的更优,必须注意讨论一下。

  不妨令g[i][j]表示i跳2^j的轮回之后可以到达的位置,一次轮回至少2个位置,所以j顶多为16。f[i][j][1]表示从点i跳过2^j个轮回之后小A走过的距离,f[i][j][0]表示从点i跳过2^j个轮回之后小B走过的距离.

  更新很简单:

   g[i][j]=g[g[i][j-1]][j-1];
        f[i][j][0]=f[i][j-1][0]+f[g[i][j-1]][j-1][0];
        f[i][j][1]=f[i][j-1][1]+f[g[i][j-1]][j-1][1];

  预处理一下g数组和f数组,到这里我第一次又写萎了一个地方,就是j的循环在外,i的在内才能保证每次计算时要用到的值都已经计算出来了。

  之后就是两个询问。第一个询问直接for一遍,模拟的跑一下看从哪个结点出来那个比值最小,注意处理边界条件,就是有可能最后一次小A还可以再走一次。第二种询问也是一样的做法,也要讨论一下边界,因为我们是倍增的模式,所以统计的次数是log级别的,时间复杂度很对。就是代码有点长,细节多。。。

  代码如下:

  1. //It is made by jump~
  2. #include <iostream>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <cstdio>
  6. #include <cmath>
  7. #include <algorithm>
  8. #include <ctime>
  9. #include <vector>
  10. #include <queue>
  11. #include <map>
  12. #include <set>
  13. #ifdef WIN32
  14. #define OT "%I64d"
  15. #else
  16. #define OT "%lld"
  17. #endif
  18. using namespace std;
  19. typedef long long LL;
  20. const int MAXN = ;
  21. const int inf = ;
  22. int n,m,h[MAXN],S;
  23. LL X0,cun;
  24. int jump[MAXN][];//A:1 B:0
  25. int g[MAXN][];//2^17大于10w ,g[i][j]表示i跳2^j的轮回之后可以到达的位置,一次轮回至少2个位置,16次方即可
  26. LL f[MAXN][][];//f[i][j][1]表示从点i跳过2^j个轮回之后小A走过的距离,f[i][j][0]表示从点i跳过2^j个轮回之后小B走过的距离
  27. LL ans1,ans2;
  28. double daan;
  29. LL ans;
  30. set<int>bst;
  31. map<int,int>mp;
  32.  
  33. inline int getint()
  34. {
  35. int w=,q=;
  36. char c=getchar();
  37. while((c<'' || c>'') && c!='-') c=getchar();
  38. if (c=='-') q=, c=getchar();
  39. while (c>='' && c<='') w=w*+c-'', c=getchar();
  40. return q ? -w : w;
  41. }
  42.  
  43. inline void find_place(){
  44. int t; LL tong1,tong2;
  45. int pos; double pp; int jilu=-;
  46. for(int i=;i<=n;i++) {
  47. t=; tong1=; tong2=; pos=i; X0=cun;
  48. for(;t>=;t--) {
  49. if(g[pos][t]==) continue;
  50. if(X0<f[pos][t][]+f[pos][t][]) continue;
  51. X0-=f[pos][t][]+f[pos][t][];
  52. tong1+=f[pos][t][]; tong2+=f[pos][t][];
  53. pos=g[pos][t];
  54. }
  55. if(X0>=f[pos][][]) X0-=f[pos][][],tong2+=f[pos][][];
  56. if(tong1==) continue;
  57. pp=(double)tong2/tong1;
  58. if(pp<daan) daan=pp,jilu=i;
  59. else if(pp==daan && h[i]>h[jilu]) jilu=i;
  60. }
  61. printf("%d\n",jilu);
  62. }
  63.  
  64. inline void go(){
  65. int t=;
  66. for(;t>=;t--) {
  67. if(g[S][t]==) continue;
  68. if(X0<f[S][t][]+f[S][t][]) continue;
  69. X0-=f[S][t][]+f[S][t][];
  70. ans1+=f[S][t][]; ans2+=f[S][t][];
  71. S=g[S][t];
  72. }
  73. if(X0>=f[S][][]) X0-=f[S][][],ans2+=f[S][][];
  74. printf("%lld %lld\n",ans2,ans1);
  75. }
  76.  
  77. inline void work(){
  78. n=getint(); for(int i=;i<=n;i++) h[i]=getint();
  79. bst.insert(inf); bst.insert(-inf); bst.insert(h[n]);
  80. int ql,qr,nowl,nowr; for(int i=;i<=n;i++) mp[h[i]]=i;
  81. for(int i=n-;i>=;i--) {
  82. ql=*--bst.lower_bound(h[i]); qr=*bst.lower_bound(h[i]);
  83. if(ql==-inf) {
  84. ql=*++bst.lower_bound(qr);
  85. jump[i][]=mp[qr];
  86. if(ql!=inf) {
  87. jump[i][]=mp[ql];
  88. f[i][][]=abs(h[ jump[jump[i][]][] ]-h[jump[i][]]);
  89. g[i][]=jump[jump[i][]][];
  90. f[i][][]=ql-h[i];
  91. }
  92. }
  93. else if(qr==inf) {
  94. qr=*--bst.lower_bound(ql); jump[i][]=mp[ql];
  95. if(qr!=-inf) {
  96. jump[i][]=mp[qr];
  97. f[i][][]=abs(h[ jump[jump[i][]][] ]-h[jump[i][]]);
  98. g[i][]=jump[jump[i][]][];
  99. f[i][][]=h[i]-qr;
  100. }
  101. }
  102. else{
  103. nowl=abs(h[i]-ql); nowr=abs(h[i]-qr);
  104. if(nowl<nowr) {
  105. jump[i][]=mp[ql]; ql=*--bst.lower_bound(ql);
  106. if(ql!=-inf) {
  107. nowl=abs(h[i]-ql); if(nowl<=nowr) qr=ql;
  108. }
  109. nowr=abs(qr-h[i]);
  110. jump[i][]=mp[qr];
  111. g[i][]=jump[jump[i][]][];
  112. f[i][][]=nowr; f[i][][]=abs(h[ jump[jump[i][]][] ]-h[jump[i][]]);
  113. }
  114. else if(nowl==nowr) {
  115. jump[i][]=mp[qr]; jump[i][]=mp[ql];
  116. g[i][]=jump[jump[i][]][];
  117. f[i][][]=nowr; f[i][][]=abs(h[ jump[jump[i][]][] ]-h[jump[i][]]);
  118. }
  119. else{
  120. jump[i][]=mp[qr]; qr=*++bst.lower_bound(qr);
  121. if(qr!=inf) {
  122. nowr=abs(h[i]-qr); if(nowl>nowr) ql=qr;
  123. }
  124. nowl=abs(ql-h[i]);
  125. jump[i][]=mp[ql];
  126. g[i][]=jump[jump[i][]][];
  127. f[i][][]=nowl; f[i][][]=abs(h[ jump[jump[i][]][] ]-h[jump[i][]]);
  128. }
  129. }
  130. bst.insert(h[i]);
  131. }
  132.  
  133. for(int j=;j<=;j++)//注意顺序!!!
  134. for(int i=;i<=n;i++) {
  135. g[i][j]=g[g[i][j-]][j-];
  136. f[i][j][]=f[i][j-][]+f[g[i][j-]][j-][];
  137. f[i][j][]=f[i][j-][]+f[g[i][j-]][j-][];
  138. }
  139.  
  140. cun=X0=getint(); m=getint();
  141. daan=1e20; find_place();
  142. while(m--) {
  143. S=getint(); X0=getint();
  144. ans1=; ans2=; go();
  145. }
  146. }
  147.  
  148. int main()
  149. {
  150. work();
  151. return ;
  152. }

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

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

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

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

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

  3. CH5701 开车旅行

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

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

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

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

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

  6. 开车旅行 【NOIP2012 D1T3】

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

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

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

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

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

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

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

随机推荐

  1. 一个可以模拟GET,POST,PUT,DELET请求的HTTP在线工具

    一个简陋的HTTP请求工具,UI比较丑陋.0.0,可以用于接口调试. 之前在调试公司的远程接口的时候用的是curl,后来也在网上找到几种Http请求模拟的客户端程序.当时后来发现google app ...

  2. IIS中使用ASP.NET MVC的经验总结

    在这篇文章中我们学习在不同版本的IIS中使用ASP.NET MVC和URL Routing.我们学习针对IIS7.0.IIS6.0和更早版本的IIS的处理策略. ASP.NET MVC框架依赖于URL ...

  3. Sphinx(Coreseek)安装和使用指南

    1.安装 1.1安装mmseg ./bootstrap # 必须执行,不然安装会失败 ./configure --prefix=/usr/local/mmseg- #指定安装目录 make make ...

  4. [LeetCode] Remove Duplicates from Sorted Array II [27]

    题目 Follow up for "Remove Duplicates": What if duplicates are allowed at most twice? For ex ...

  5. 【Atheros】内核调试及网卡加载等问题小结

    我做的其他很多工作就比较有针对性了,不是什么大众性的问题,比如加统计代码.实现自己的速率调整算法或者加一些自己的控制什么的,就不再单独介绍了,最后呢再罗列一些小问题,供参考. 1. 加载模块(执行wi ...

  6. android-support-v4.jar异常解决方法

    1.当一个项目引入其他library项目时,会出现android-support-v4.jar冲突问题: 解决:将library项目中的android-support-v4.jar更新到最新,方法右键 ...

  7. 将PHP 5.3.3 (cli)升级到PHP 5.6.31 (cli)

    centos默认系统安装的是php5.3 [root@sz-local1 scripts]# rpm -qa |grep phpphp-pdo-5.3.3-47.el6.x86_64php-mysql ...

  8. extendgcd模板

    看了数论第一章,终于搞懂了扩展欧几里德,其实就是普通欧几里德的逆推过程. // ax+by = gcd(a,b) ->求解x,y 其中a,b不全为0,可以为负数// 复杂度:O(log2a)vo ...

  9. 软件测试人员需要精通的开发语言(3)--- Linux

    Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户.多任务.支持多线程和多CPU的操作系统.不得不说下,中国产的红旗系统,牛的一逼,造价很贵,但具体何用处估 ...

  10. EasyNVR无插件摄像机直播之:摄像机网页低延时无插件直播实现

    背景需求 对于摄像机直播,客户反馈的最多就是实现web直播.摆脱插件,可以自定义集成等问题, 对于熟悉EasyNVR已经完美的解决了这些问题.然而对于web播放也存在一些问题,通常我们web播放RTM ...