题意

题目链接

Sol

咕了一年的题解。。

并不算是很难,只是代码有点毒瘤

\(f[i][j]\)表示从\(i\)号节点出发走了\(2^j\)轮后总的距离

\(da[i][j]\)同理表示\(a\)的距离,\(db[i][j]\)与\(da\)同理

倍增优化一下

注意最后\(a\)可能还会走一次

  1. #include<bits/stdc++.h>
  2. #define Pair pair<int, int>
  3. #define MP make_pair
  4. #define fi first
  5. #define se second
  6. #define Fin(x) {freopen(#x".in","r",stdin);}
  7. #define pb(x) push_back(x)
  8. #define LL long long
  9. //#define int long long
  10. using namespace std;
  11. const int MAXN = 1e5 + 10;
  12. LL INF = 2e9 + 10, B = 20;
  13. inline int read() {
  14. char c = getchar(); int x = 0, f = 1;
  15. while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
  16. while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
  17. return x * f;
  18. }
  19. int N, jp[MAXN][21], nxa[MAXN], nxb[MAXN], flag[MAXN], h[MAXN];
  20. LL f[MAXN][21], da[MAXN][21], db[MAXN][21];
  21. struct Node {
  22. LL Hi, id;
  23. bool operator < (const Node &rhs) const{
  24. return Hi == rhs.Hi ? h[id] < h[rhs.id] : Hi < rhs.Hi;
  25. }
  26. };
  27. int get(int x, int y) {
  28. return abs(h[x] - h[y]);
  29. }
  30. set<Node> s;
  31. void Pre() {
  32. s.insert((Node) {-INF * 2, 0}); s.insert((Node) {INF * 2, 0});
  33. s.insert((Node) {-INF * 2 + 1, 0}); s.insert((Node) {INF * 2 + 1, 0});
  34. s.insert((Node) {h[N], N});
  35. memset(f, 0x3f, sizeof(f));
  36. for(int i = N - 1; i >= 1; i--) {
  37. set<Node> :: iterator y = s.lower_bound((Node) {h[i], i});
  38. vector<Node> tmp; tmp.clear();
  39. tmp.push_back((Node) {get(y -> id, i), y -> id}); y++;
  40. tmp.push_back((Node) {get(y -> id, i), y -> id}); y--; y--;
  41. tmp.push_back((Node) {get(y -> id, i), y -> id}); y--;
  42. tmp.push_back((Node) {get(y -> id, i), y -> id});
  43. sort(tmp.begin(), tmp.end());
  44. nxa[i] = tmp[1].id;
  45. nxb[i] = tmp[0].id;
  46. s.insert((Node) {h[i], i});
  47. if(tmp[1].id != 0 && tmp[0].id != 0) f[i][0] = tmp[1].Hi + db[tmp[1].id][0];
  48. jp[i][0] = nxb[nxa[i]];
  49. da[i][0] = get(i, nxa[i]);
  50. db[i][0] = get(i, nxb[i]);
  51. }
  52. for(int j = 1; j <= B; j++)
  53. for(int i = 1; i <= N; i++) {
  54. if(jp[i][j - 1])
  55. jp[i][j] = jp[jp[i][j - 1]][j - 1],
  56. f[i][j] = f[i][j - 1] + f[jp[i][j - 1]][j - 1],
  57. da[i][j] = f[i][j] == INF ? 0 : da[i][j - 1] + da[jp[i][j - 1]][j - 1];
  58. }
  59. }
  60. void print() {
  61. for(int i = 1; i <= N; i++) printf("**%d\n", f[i][0]);
  62. }
  63. Pair Query(int pos, int val) {
  64. LL a1 = 0, a2 = 0;
  65. for(int i = B; ~i; i--)
  66. if(f[pos][i] <= val)
  67. val -= f[pos][i], a1 += da[pos][i], a2 += f[pos][i] - da[pos][i], pos = jp[pos][i];
  68. if(da[pos][0] <= val) a1 += da[pos][0];
  69. return MP(a1, a2);
  70. }
  71. signed main() {
  72. // freopen("drive3.in", "r", stdin);
  73. // freopen("a.out", "w", stdout);
  74. N = read();
  75. for(int i = 1; i <= N; i++) h[i] = read(); h[0] = INF;
  76. Pre();
  77. // print();
  78. int X0 = read(), ans = N;
  79. double tmp = 1e22;
  80. for(int i = 1; i <= N; i++) {
  81. Pair now = Query(i, X0);
  82. if(now.se == 0) continue;
  83. if((double)now.fi / now.se < tmp) tmp = (double)now.fi / now.se, ans = i;
  84. }
  85. printf("%d\n", ans);
  86. int M = read();
  87. while(M--) {
  88. int Si = read(), Mi = read();
  89. Pair now = Query(Si, Mi);
  90. printf("%d %d\n", now.fi, now.se);
  91. }
  92. return 0;
  93. }

洛谷P1081 开车旅行(倍增)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. NOIP 2012 洛谷P1081 开车旅行

    Description: 就是两个人开车,只能向东开.向东有n个城市,城市之间的距离为他们的高度差.A,B轮流开车,A喜欢到次近的城市,B喜欢到最近的城市.如果车子开到底了或者车子开的路程已经超过了限 ...

  7. 洛谷P1081 开车旅行

    题目 双向链表+倍增+模拟. \(70pts\): 说白了此题的暴力就是细节较多的模拟题. 我们设离\(i\)城市最近的点的位置为\(B[i]\),第二近的位置为\(A[i]\).设\(A\)或\(B ...

  8. 洛谷P1081——开车旅行

    传送门:QAQQAQ 题意注意点: 1.是从前往后走,不能回头 2.小A小B轮流开,先小A开,而小A是到第二近的点(这点调试的时候查了好久) 3.若绝对值差相同海拔低的更近,而第一个询问若比值相同是海 ...

  9. 洛谷P1081 开车旅行70分

    https://www.luogu.org/problem/show?pid=1081 太遗憾了明明写出来了,却把最小值初始值弄小了,从第二个点开始就不可能对了.70分! #include<io ...

随机推荐

  1. sql92和sql99

    sql1992sql分类 1.笛卡尔积 (表乘表) 2.等值连接 表的连接条件使用“=” 3.非等值连接 表的连接条件使用“>.>=. <.<=.!=.any等” 4.自连接 ...

  2. vim编辑器基本操作及文件权限,sudo命令等介绍

    一:vim 操作命令,在命令模式下操作 pageup 往上翻页 pagedown 往下翻页 H 移动到屏幕首行 gg 移动光标到文档的首行 前面加数字n表示移动到n行内容 G 移动到文档最后一行/查找 ...

  3. python之类与对象(4)

    5. 类的继承 继承可谓是重中之重,也是面向对象编程的核心内容之一.子类可以继承父类的属性以及方法.作为一名测试人员,学习了类之后,我们可以很好的把代码与数据分离开来,有了基本的封装思想.接下来我们将 ...

  4. 123th LeetCode Weekly Contest Broken Calculator

    On a broken calculator that has a number showing on its display, we can perform two operations: Doub ...

  5. iis上部署本地数据库LocalDB的方法

    1. iis应用程序池的标识设置为"ApplicationPoolIdentify"(比较安全) 2. 不要将数据库物理文件保存在网站的物理路径内,因为iis应用程序池的标识为Ap ...

  6. Quartz .net 一直运行失败

    使用了新的: Quartz.NET 2.6.2 https://github.com/quartznet/quartznet/releases IScheduler scheduler = StdSc ...

  7. 数据库SQL(1)

    EG1:db.LpOutputGroups.GroupBy(q => q.CalcGroupDesc).ToList().OrderByDescending(m => m.First(). ...

  8. Python爬虫:常用的浏览器请求头User-Agent(转)

    原文地址:https://blog.csdn.net/mouday/article/details/80182397 user_agent = [ "Mozilla/5.0 (Macinto ...

  9. Redis中算法之——Raft算法

    Sentinel系统选举领头的方法是对Raft算法的领头选举方法的实现. 在分布式系统中一致性是很重要的.1990年Leslie Lamport提出基于消息传递的一致性算法Paxos算法,解决分布式系 ...

  10. (转)nginx location在配置中的优先级

    原文:https://www.bo56.com/nginx-location%E5%9C%A8%E9%85%8D%E7%BD%AE%E4%B8%AD%E7%9A%84%E4%BC%98%E5%85%8 ...