[NOIP2012提高组]开车旅行

这道题的主要思想是倍增。其次的难点在于预处理,这里使用链表来实现。

复杂度:$O(n log n)$

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <cmath>
  6 
  7 using namespace std;
  8 
  9 #define re register
 10 #define LL long long
 11 #define rep(i, x, y) for (register int i = x; i <= y; ++i)
 12 #define repd(i, x, y) for (register int i = x; i >= y; --i)
 13 #define maxx(a, b) a = max(a, b)
 14 #define minn(a, b) a = min(a, b)
 15 #define inf 1e17
 16 
 17 inline LL read() {
 18     LL w = 0, f = 1; char c = getchar();
 19     while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar();
 20     while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ 48), c = getchar();
 21     return w * f;
 22 }
 23 
 24 const int maxn = 1e5 + 5;
 25 
 26 struct Dist {
 27     LL A, B, to;
 28 } f[20][maxn];
 29 
 30 struct Node {
 31     int id;
 32     LL v;
 33 } nd[maxn];
 34 
 35 int L[maxn], R[maxn];
 36 
 37 int n, m, jp1[maxn], jp2[maxn];
 38 LL H[maxn], X0;
 39 
 40 int comp(int x, int a, int b) {
 41     re LL va = abs(H[x] - H[a]), vb = abs(H[x] - H[b]);
 42     if (va < vb) return a;
 43     else if (va == vb) return H[a] < H[b] ? a : b;
 44     else return b;
 45 }
 46 
 47 bool cmp1(Node a, Node b) {
 48     return a.v < b.v;
 49 }
 50 
 51 bool cmp2(Node a, Node b) {
 52     return a.id < b.id;
 53 }
 54 
 55 void solve(int s, LL X, LL &A, LL &B) {
 56     repd(i, log2(n - s + 1), 0)
 57         if (f[i][s].A + A + f[i][s].B + B <= X) {
 58             A += f[i][s].A;
 59             B += f[i][s].B;
 60             s = f[i][s].to;
 61         }
 62     if (A + abs(H[jp1[s]] - H[s]) + B <= X) A += abs(H[jp1[s]] - H[s]);
 63 }
 64 
 65 int main() {
 66     n = read();
 67     rep(i, 1, n) {
 68         nd[i].v = H[i] = read();
 69         nd[i].id = i;
 70     }
 71     
 72     sort(nd + 1, nd + n + 1, cmp1);
 73     
 74     rep(i, 2, n) L[nd[i].id] = nd[i-1].id;
 75     rep(i, 1, n-1) R[nd[i].id] = nd[i+1].id;
 76     L[0] = L[nd[1].id] = 0;
 77     R[n+1] = R[nd[n].id] = n+1;
 78     
 79     H[0] = H[n+1] = inf;
 80     
 81     rep(i, 1, n) {
 82         re int second = comp(i, L[i], R[i]);
 83         re int first = comp(i, L[i] + R[i] - second, comp(i, L[L[i]], R[R[i]]));
 84         jp1[i] = first, jp2[i] = second;
 85         L[R[i]] = L[i];
 86         R[L[i]] = R[i];
 87     }
 88     
 89     rep(i, 1, n) {
 90         f[0][i].to = jp2[jp1[i]];
 91         f[0][i].A = abs(H[jp1[i]] - H[i]);
 92         if (jp2[jp1[i]] == n+1) f[0][i].B = inf;
 93         else f[0][i].B = abs(H[jp1[i]] - H[jp2[jp1[i]]]);
 94     }
 95     rep(x, 1, log2(n))
 96         rep(i, 1, n) {
 97             f[x][i].to = f[x-1][f[x-1][i].to].to;
 98             f[x][i].A = f[x-1][i].A + f[x-1][f[x-1][i].to].A;
 99             f[x][i].B = f[x-1][i].B + f[x-1][f[x-1][i].to].B;
100             if (f[x][i].A > inf) f[x][i].A = inf*2;
101             if (f[x][i].B > inf) f[x][i].B = inf*2;
102         }
103     
104     X0 = read();
105     
106     H[0] = -inf;
107     re LL maxi = 0, maxA = inf, maxB = 1;
108     
109     rep(i, 1, n) {
110         #define update maxA = A, maxB = B, maxi = i
111         re LL A = 0, B = 0;
112         solve(i, X0, A, B);
113         if (B != 0) {
114             if ((double)maxA / maxB > (double)A / B) update;
115             else if (fabs((double)maxA / maxB - (double)A / B) < 1e-9 && H[i] > H[maxi]) update;
116         }
117     }
118     
119     printf("%lld\n", maxi);
120     
121     m = read();
122     
123     while (m--) {
124         re int s = read();
125         re LL X = read(), A = 0, B = 0;
126         solve(s, X, A, B);
127         printf("%lld %lld\n", A, B);
128     }
129     
130     return 0;
131 }

 

posted @ 2018-11-03 18:01  AC-Evil  阅读(471)  评论(0编辑  收藏  举报