這道題最難的應該是預處理。。。
首先用$set$從後往前預處理出每乙個點海拔差絕對值得最大值和次大值
因為當前城市的下標只能變大,對於點$i$,在$set$中二分找出與其值最接近的下標
然後再$set$中將左右各兩個下標處理出來,取最大值和次小值
預處理完畢
將每一次小a和小b的開車看為一輪開車
然後用$g[i][j]$表示從第i個點出發經過了$2^$輪開車到達的點
$la[i][j]$表示從第i個點出發經過了$2^$輪開車小a開的路程
$lb[i][j]$表示從第i個點出發經過了$2^$輪開車小b開的路程
然後就是倍增處理
還有要注意,當完整的一輪無法在進行後,小a還有可能再開一輪車,進行判斷即可
#include #define ll long long#define inf 1e9
using
namespace
std;
const ll maxn=100100
;ll n,x0,a[maxn],b[maxn],g[maxn][
32];
ll h[maxn],
where
,ding,m;
ll la[maxn][
32],lb[maxn][32
];double
min;
set>s;
bool cmp(paira,pairb)
intmain()
if (it!=s.end())
k.push_back(*it);
if(bl)
it--;
it--;
if (it!=be)
if (it!=be)
k.push_back(*it);//處理出左右4個點
ding=h[i];
sort(k.begin(),k.end(),cmp);
b[i]=k[0
].second;//取最大
a[i]=k[1
].second;//取次大
s.insert(make_pair(h[i],i));
}for (ll i=1;i<=n;i++)
}for (ll i=1;i<=30;i++)
else
g[j][i]=-1
; }
}scanf(
"%lld
",&x0);
min=1.0e18+10
;
where=0
;
for (ll i=1;i<=n;i++)
}if (a[now]!=-1 && ta+tb+abs(h[now]-h[a[now]])<=x0)
double
temp;
if (tb==0
) temp=1.0e18
;
else
temp=(double)(1.0*ta)/(1.0*tb);
if (tempelse
if (temp==min)
}printf(
"%lld\n
",where
); scanf(
"%lld
",&m);
for (ll i=1;i<=m;i++)
}if (a[now]!=-1 && ta+tb+abs(h[now]-h[a[now]])<=x)
printf(
"%lld %lld\n
",ta,tb);
}}
NOIP2012 洛谷1081 開車旅行
題目描述 小 a 和小 b 決定利用假期外出旅行,他們將想去的城市從 1 到 n 編號,且編號較小的 城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 i 的海拔高度為 hi,城市 i 和城市 j 之間的距離 d i,j 恰好是這兩個城市海拔高度之差的絕對值,即 d i,j hi ...
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 位置出...