城市\(i\)的海拔高度為\(h_i\)(各不相同)。定義距離為海拔差的絕對值
小\(a\)和小\(b\)輪流開車。從\(s\)起,一直向東行駛。
小\(a\)會選擇第二近的城市作為目的地。小\(b\)選擇乙個最近的城市作為目的地。(如果當前城市到兩個城市的距離相同,則認為離海拔低的那個城市更近)。如果無法再開了,或者到達目的地會使行駛的總距離超出\(x\)公里,他們就會結束旅行。
單次詢問:給定\(x\),問從哪個城市出發,小\(a\)行的路程與小\(b\)行的路程的比值最小
多次詢問:給定\(s\)和\(x\),問小\(a\)行的路程與小\(b\)行的路程
\(1 \leq n \leq 10^5,1 \leq m \leq 10^5\)
首先肯定要解決乙個問題,小\(a\)和小\(b\)的目的地在**。
先排序,然後從第乙個城市開始,比較\(i-1,i-2,i+1,i+2\)處距離。
很顯然,由於是第乙個點,這個時候找到的任何點一定在它東邊。
同樣的,找完第乙個點後將第乙個點刪除,那麼第二個點自然成為了第乙個點,依次下去,便在\(o(n)\)的複雜度內完成了預處理。
接下來,就可以想到用倍增來解決。
用\(f[i][j]\)表示從\(j\)出發第\(2^i\)天到達的城市,發現除了\(i=0\)時是\(a\)在開其他都是\(b\)開,所以轉移就很簡單了\(f[i][j]=f[i-1][f[i-1][j]];\)
那麼求出了路徑,距離只要減一減就好了。
用\(g[i][j][0]\)表示從\(j\)出發第\(2^i\)天\(a\)開的,用\(g[i][j][1]\)表示從\(j\)出發第\(2^i\)天\(b\)開的,轉移:
\(g[i][j][0]=g[i-1][j][0]+g[i-1][f[i-1][j]][0];\)
\(g[i][j][1]=g[i-1][j][1]+g[i-1][f[i-1][j]][1];\)
接下來的詢問只要每次倍增湊距離就好了
對於第乙個詢問列舉出發點再比較
時間複雜度\(o((n+m)logn)\)
#include const int n=100005;
double inf=1000000000;
using std::sort;
int a[n],b[n],next[n],last[n],c[n],n,m,f[21][n],x,ans=0,s;
long long h[n],suma,sumb,g[21][n][2];
bool cmp(int x,int y)
}int main()
}printf("%d\n",ans);
scanf("%d",&m);
for (int i=1;i<=m;i++)
}
要注意\(h[0]\)的初始化,原來沒仔細看資料結果爆了\(4\)發 luogu p1081 開車旅行
傳送門 此題為複雜細節題,無法總結題意,所以給出原題 小 text 和小 text 決定利用假期外出旅行,他們將想去的城市從 1 到 n 編號,且編號較小的城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 i 的海拔高度為 h i 城市 i 和城市 j 之間的距離 d 恰好是這兩個...
luogu p1081 開車旅行
傳送門此題為複雜細節題,無法總結題意,所以給出原題 小 text 和小 text 決定利用假期外出旅行,他們將想去的城市從 1 到 n 編號,且編號較小的城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 i 的海拔高度為 h i 城市 i 和城市 j 之間的距離 d 恰好是這兩個城...
P1081 開車旅行
p1081 開車旅行 排序優化 倍增 其實這道題一開始是一點也沒有頭緒,知道有高人指點了一下。說並不需要拘束於出發點和路徑長度,也就是問題1.2。不過乙個是固定路徑長度的詢問,另乙個是給定起點和路徑長度的詢問。所以問題一和問題二是可以使用乙個函式解決的,而且對於乙個城市來說,在不考慮路程的情況下,路...