其實就是個大模擬。
首先,根據題意,小a和小b從任意乙個城市開始走,無論\(x\)如何,其路徑是一定唯一的。
顯然對於兩問都可以想出乙個\(o(n^2)\)的暴力,即直接一步一步地向右走。
首先,我們當然需要知道a,b在每個城市的下一步如何走,記\(nexta(i),nextb(i)\)為a,b在\(i\)處時,下一步走到的城市編號。
考慮如何高效(複雜度小於等於\(o(nlogn)\))維護兩個\(next\)。
顯然不能直接維護每個城市與其後面的城市的差值,再好的資料結構也會到\(o(n^2)\)。
不妨考慮從後往前依次插入\(h_i\),然後動態維護\(h_i\sim h_n\)的有序集合。這樣的話,在有序集合中,最小的差值一定要麼是\(h_i\)與其前驅,要麼就是與其後繼的差值。次小的差值,就是\(h_i\)前驅、前驅的前驅、後繼、後繼的後繼與\(h_i\)的差值的次小值。這個問題,平衡樹解決之,預處理\(o(nlogn)\)。
下面考慮走\(k\)步的情況,當前步是a走還是b走與步數的奇偶性有關,因此我們還要分開討論。
那麼,我們不妨考慮以此為基礎進行優化,比如優化到\(o(nlogn)\)。顯然地,對於這樣的問題,我們可以倍增預處理,\(o(logn)\)詢問。
接下來考察我們需要什麼資訊,分別是\(i\)向後走\(k\)步的城市,a和b從\(i\)向後走\(k\)步的路程。
設\(f[0/1][i][j]\)為從\(i\)位置,0a,1b向後走\(2^j\)步的城市。
顯然\[f[0][i][0]=nexta(i)\\f[1][i][0]=nextb(i)
\]由於,走\(2^0\)步是走奇數步,有轉移
\[f[0][i][1]=f[1][f[0][i][0]][0]\\f[1][i][1]=f[0][f[1][i][0]][0]
\]對於走\(2^j\)步,有
\[f[0][i][j]=f[0][f[0][i][j-1]][j-1]\\f[1][i][j]=f[1][f[1][i][j-1]][j-1]
\]設\(da[0/1][i][j]\)表示從\(i\)位置,a向後走\(2^j\)步的路程,且現在(當前步)是0a,1b在開車,還沒走時的a開的距離
顯然\[da[0][i][0]=dist(i,nexta(i))\\da[1][i][0]=0
\]有轉移
\[da[0][i][1]=da[0][i][0]+da[1][f[0][i][0]][0]\\da[1][i][1]=da[1][i][0]+da[0][f[1][i][0]][0]\\da[0][i][j]=da[0][i][j-1]+da[0][f[0][i][j-1]][j-1]\\da[1][i][j]=da[1][i][j-1]+da[1][f[1][i][j-1]][j-1]
\]設\(db[0/1][i][j]\)表示從\(i\)位置,b向後走\(2^j\)步的路程,且現在是0a,1b在開車。
跟\(da\)差別不大,不再贅述。
預處理完成之後,我們開始考慮題述問題。
對於第一問,對給出的\(x_0\),我們列舉城市\(s_i\),倍增統計走\(x_0\)步的答案(當然超出\(n\)要特判),\(o(nlogn)\)解決之。
對於第二問,同樣的,對於每一組\(s_i,x_i\),直接倍增統計即可,複雜度\(o(mlogn)\)。
總複雜度在\(o((n+m)logn)\)左右,完全可以通過本題。
注意,這道題的細節之數量足以讓人去世。
**未經重構,很醜。
#include#include#include#include#include#include#include#include#include#include#include#define inf 0x7fffffff
#define pi acos(-1.0)
#define n 100010
#define mod 2520
#define e 1e-12
#define ll long long
using namespace std;
inline ll read()
while(c>='0'&&c<='9')
return x*f;
}seth;
mapmp;
int t;
ll n,a[n],na[n],nb[n],f[2][n][21],da[2][n][21],db[2][n][21];
int main()
else
f[0][i][0]=na[i];f[1][i][0]=nb[i];
da[0][i][0]=abs(a[i]-a[na[i]]);
db[1][i][0]=abs(a[i]-a[nb[i]]);
} for(int j=1;j<=t;++j)else
} }/
int x0=read(),s0=0;
double ans=1e14,nans=1e14;//task 1
for(int i=1;i<=n;++i)
} nans=(double)resa/(double)resb;
if(nans=0;--j)
} printf("%lld %lld\n",resa,resb);
} return 0;
}
P1081 開車旅行
p1081 開車旅行 排序優化 倍增 其實這道題一開始是一點也沒有頭緒,知道有高人指點了一下。說並不需要拘束於出發點和路徑長度,也就是問題1.2。不過乙個是固定路徑長度的詢問,另乙個是給定起點和路徑長度的詢問。所以問題一和問題二是可以使用乙個函式解決的,而且對於乙個城市來說,在不考慮路程的情況下,路...
P1081 開車旅行
傳送門 用倍增的思想 設 a i 表示a在 i 位置走一步到達的城市以及經過的路程 這裡我用結構體存a i b同理 設 f i j 表示從 i 位置出發,走 2 j 輪後到達的城市 一輪即ab各走一次 dis i j 表示從 i 位置出發,走 2 j 輪後經過總路程 da i j 表示從 i 位置出...
洛谷P1081 開車旅行 (Treap 倍增)
題目傳送門 題目分析 這題的兩個問其實是差不多的。第一問給出了x0,我們列舉起點s,就相當於變成了n個第二類詢問 s x0 1 s n 於是現在原問題變成了 給出 s,x 如何快速求s開始往下走不超過x距離時,a,b各走的距離?然後用資料結構預處理出a,b到達每乙個點之後會走哪個點,詢問時倍增往後跳...