1. 程式人生 > >Luogu1081 NOIP2012D1T3 開車旅行 倍增

Luogu1081 NOIP2012D1T3 開車旅行 倍增

最小和 處理 ++ end begin 使用 log () fir

題目傳送門

為什麽NOIP的題目都這麽長qwq


話說2012的D1T3和D2T3都是大火題啊qwq

預處理神題

對於這種跳跳跳的題目考慮使用倍增優化枚舉。先預處理某個點之後距離最小和次小的城市,然後倍增預處理一大堆東西。設$f_i$表示從$A$開始開$2^i$次車到達的地點,$g_i$表示從$B$開始開$2^i$次車到達的地點,$k_{i,0/1}$表示從$A$開始開$2^i$次車$A$或$B$經過的路程,$l_{i,0/1}$表示從$B$開始開$2^i$次車$A$或$B$經過的路程。註意邊界與越界情況的處理。

接下來就可以直接拼湊法跳了,時間復雜度$O((n+q)logn)$

  1 #include<bits/stdc++.h>
  2
#define MAXN 100001 3 using namespace std; 4 inline int read(){ 5 int a = 0 , k = 1; 6 char c = getchar(); 7 while(!isdigit(c) && c != -) c = getchar(); 8 if(c == -) k = -k , c = getchar(); 9 while(isdigit(c)) a += (a << 3) + a + (c ^ 0) , c = getchar();
10 return a * k; 11 } 12 long long la[MAXN][17][2] , lb[MAXN][17][2]; 13 int f[MAXN][17][2] , h[MAXN] , N; 14 set < pair < int , int > > s; 15 inline int abs(int a){return a > 0 ? a : -a;} 16 pair < int , int > cul(int ss , int x){ 17 pair < int , int > t(0 , 0
); 18 for(int i = log(N) / log(2) ; i >= 0 ; i--) 19 if(f[ss][i][0] && (long long)t.first + t.second + la[ss][i][0] + lb[ss][i][0] <= x){ 20 t.first += la[ss][i][0]; 21 t.second += lb[ss][i][0]; 22 ss = f[ss][i][0]; 23 } 24 return t; 25 } 26 int main(){ 27 memset(la , 1 , sizeof(la)); memset(lb , 1 , sizeof(lb)); 28 N = read(); 29 for(int i = 1 ; i <= N ; i++) h[i] = read(); 30 s.insert(make_pair(h[N] , N)); 31 s.insert(make_pair(h[N - 1] , N - 1)); 32 if(N - 1) f[N - 1][0][1] = N; 33 for(int i = N - 2 ; i ; i--){ 34 set < pair < int , int > > :: iterator t = s.insert(make_pair(h[i] , i)).first; 35 if(t == s.begin()){ 36 f[i][0][1] = (++s.begin())->second; 37 f[i][0][0] = (++++s.begin())->second; 38 continue; 39 } 40 set < pair < int , int > > :: iterator t1 = --t , t2 = ++++t; 41 if(t2 == s.end()){ 42 f[i][0][1] = t1->second; 43 f[i][0][0] = (--t1)->second; 44 } 45 else{ 46 if(h[i] - t1->first <= t2->first - h[i]){ 47 f[i][0][1] = t1->second; 48 if(t1 == s.begin()){ 49 f[i][0][0] = t2->second; 50 continue; 51 } 52 --t1; 53 } 54 else{ 55 f[i][0][1] = t2->second; 56 if(++t2 == s.end()){ 57 f[i][0][0] = t1->second; 58 continue; 59 } 60 } 61 if(h[i] - t1->first <= t2->first - h[i]) f[i][0][0] = t1->second; 62 else f[i][0][0] = t2->second; 63 } 64 } 65 for(int i = 1 ; i <= N ; i++){ 66 if(f[i][0][0]) la[i][0][0] = abs(h[i] - h[f[i][0][0]]); 67 if(f[i][0][1]) lb[i][0][1] = abs(h[i] - h[f[i][0][1]]); 68 la[i][0][1] = lb[i][0][0] = 0; 69 } 70 for(int i = 1 ; i < N ; i++){ 71 f[i][1][0] = f[f[i][0][0]][0][1]; 72 f[i][1][1] = f[f[i][0][1]][0][0]; 73 la[i][1][0] = la[i][0][0]; 74 lb[i][1][0] = lb[f[i][0][0]][0][1]; 75 la[i][1][1] = la[f[i][0][1]][0][0]; 76 lb[i][1][1] = lb[i][0][1]; 77 } 78 for(int i = 2 ; 1 << i < N ; i++) 79 for(int j = 1 ; j <= N - (1 << i) ; j++){ 80 f[j][i][0] = f[f[j][i - 1][0]][i - 1][0]; 81 f[j][i][1] = f[f[j][i - 1][1]][i - 1][1]; 82 la[j][i][0] = la[j][i - 1][0] + la[f[j][i - 1][0]][i - 1][0]; 83 lb[j][i][0] = lb[j][i - 1][0] + lb[f[j][i - 1][0]][i - 1][0]; 84 la[j][i][1] = la[j][i - 1][1] + la[f[j][i - 1][1]][i - 1][1]; 85 lb[j][i][1] = lb[j][i - 1][1] + lb[f[j][i - 1][1]][i - 1][1]; 86 } 87 int X0 = read() , dir = 1; 88 pair < int , int > maxN = cul(1 , X0); 89 for(int i = 2 ; i <= N ; i++){ 90 pair < int , int > t = cul(i , X0); 91 if(t.second && maxN.second == 0){ 92 maxN = t; 93 dir = i; 94 } 95 else if(maxN.second == 0 && t.second == 0 && h[dir] < h[i]){ 96 maxN = t; 97 dir = i; 98 } 99 else if(t.second && ((long long)maxN.first * t.second > (long long)maxN.second * t.first || maxN.first * t.second == maxN.second * t.first && h[dir] < h[i])){ 100 maxN = t; 101 dir = i; 102 } 103 } 104 printf("%d\n" , dir); 105 for(X0 = read() ; X0 ; X0--){ 106 int a = read() , b = read(); 107 pair < int , int > t = cul(a , b); 108 printf("%d %d\n" , t.first , t.second); 109 } 110 return 0; 111 }

Luogu1081 NOIP2012D1T3 開車旅行 倍增