NOIP 2012 P1081 開車旅行

2022-05-25 16:18:07 字數 1809 閱讀 5799

這道題最難的應該是預處理。。。

首先用$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 位置出...