NOIp2012 開車旅行

2022-07-24 08:21:11 字數 3242 閱讀 6272

版權yangyaojia.cnblogs.com

noip2012 day1 t3

題目大意

給出n個排成一行的城市,每個城市有乙個不同的海拔。定義兩個城市間的距離等於他們的高度差的絕對值,且絕對值相等的時候海拔低的距離近。有兩個人輪流開車,從左往右走。a每次都選最近的,b每次都選次近的。旅行時有乙個總路程x,如果兩個人的總路程》x 或 有乙個人無法按照自己的原則選擇目的城市,旅行就終止。

1.給出x0,求從哪乙個城市出發,使得a走的路程/b走的路程最小。如果b走的路程=0,則比值視為無窮大。如果有多個城市滿足要求,則輸出海拔最高的那個城市。

2.給出x和s(出發城市),求旅行終止是a的路程和b的路程。

輸入描述 input description

第一行包含乙個整數 n,表示城市的數目。

第二行有 n 個整數,每兩個整數之間用乙個空格隔開,依次表示城市 1 到城市 n 的海拔高度,即h1,h2,……,hn,且每個hi都是不同的。

第三行包含乙個整數 x0。

第四行為乙個整數 m,表示給定m組si和 xi。

接下來的m行,每行包含2個整數si和xi,表示從城市 si出發,最多行駛xi公里。

輸出描述 output description

輸出共m+1 行。

第一行包含乙個整數s0,表示對於給定的x0,從編號為s0的城市出發,小a開車行駛的路程總數與小b行駛的路程總數的比值最小。

接下來的 m 行,每行包含 2 個整數,之間用乙個空格隔開,依次表示在給定的 si和xi下小a行駛的里程總數和小b 行駛的里程總數。

樣例輸入       

4 

2 3 1 4

3 4

1 3

2 3

3 3

4 3

輸出1

1 12 0

0 00 0

【資料範圍】

對於 30%的資料,有 1≤n≤20,1≤m≤20;

對於 40%的資料,有 1≤n≤100,1≤m≤100;

對於 50%的資料,有 1≤n≤100,1≤m≤1,000;

對於 70%的資料,有 1≤n≤1,000,1≤m≤10,000;

對於100%的資料,有1≤n≤100,000,1≤m≤10,000,-1,000,000,000≤hi≤1,000,000,000,

0≤x0≤1,000,000,000,1≤si≤n,0≤xi≤1,000,000,000,資料保證 hi互不相同。

解題方案

這一道題翻了題解才做出來,我在這裡總結一下。

我們很容易可以發現,這可以用線段上的倍增來跳點。

我們可以把a和b合成一輪,這樣我們用f[i][j]帶表從第i個點跳2j輪所到達的點。

用da[i][j]代表第i個點跳2j輪所到達的點時a所走的路程。db[i][j]也是同樣的意義。

所以計算路程的方法與倍增跳點的方法一樣。關鍵是怎麼出預處理,求出da[i][0],db[i][0],與f[i][0]

其實,網上有很多介紹預處理的實現方法,但主要的思想都是這樣的:

我們可以從n到1依次將點(以其高度為關鍵字,並記下其編號)丟入乙個有序佇列。那麼如果剛加進的點序號為i,最近點與次近點只可能在i-2,i-1,i+1,i+2中。我們就可以在這裡確定陣列sa[i],代表i號點的次近點,sb[i]代表i號點最近點。因為加入的順序為n到1,所以肯定是合理的。

我們可以得到

f[i][0]=sb[sa[i]];

da[i][0]=abs(h[i]-h[sa[i]]);

db[i][0]=abs(h[sa[i]]-h[sb[sa[i]]]);

具體怎麼實現,好像可以用離散化+鍊錶,雙向鍊錶,平衡樹.....但我認為最6的還是 stl 的 set

預處理好了,我們就可以按照倍增的方法,求出再限定距離能跳的點。注意,會有情況b跳不了單a跳的了,我們要特殊處理。

對於第一問,可以列舉。o(n log n)

第二問 就是詢問 o(log n)

要開long long!

#include #include 

#include

#include

#include

#include

#include

#include

#define maxn 100000+10

#define pair pairusing

namespace

std;

long

long

n,a[maxn],sa[maxn],sb[maxn],x0,m;

long

long f[maxn][20],da[maxn][20],db[maxn][20

];long

long

read()

sets;

set:: iterator it1;

set:: iterator it2;

void

init()

}if(it2!=--s.end())

}sort(tmp+1,tmp+num+1

); sb[i]=tmp[1

].second;

if(num>=2) sa[i]=tmp[2

].second;

f[i][

0]=sb[sa[i]];

if(sa[i]) da[i][0]=abs(a[i]-a[sa[i]]);

if(sb[sa[i]]&&sa[i]) db[i][0]=abs(a[sa[i]]-a[sb[sa[i]]]);

}for(long

long j=1;(1

}}long

long query(long

long x,long

long d,long

long &xx,long

long &yy)

if(sa[a]&&ansa+ansb+da[a][0]<=d)

ansa+=da[a][0

]; xx=ansa;

yy=ansb;

}int

main()}}

printf(

"%lld\n

",bp);

scanf(

"%lld

",&m);

for(long

long i=1;i<=m;i++)

//*/

return0;

}

NOIp2012 開車旅行

傳送門 以後序列上的問題可以想一想倍增。s a i s b i sa i sb i sa i sb i 記錄在i ii這個位置讓a b a ba b開車到達的點。把a aa和b bb都跳一次稱為一輪。d is i j dis i j dis i j 表示從i ii跳2 j2 j 2j輪的總路程。p ...

Noip2012 開車旅行

小 a 和小 b 決定利用假期外出旅行,他們將想去的城市從 1 到 n 編號,且編號較小的城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 i 的海拔高度為hi,城市 i 和城市 j 之間的距離 d i,j 恰好是這兩個城市海拔高度之差的絕對值,即d i,j hi hj 旅行過程中...

NOIP2012 開車旅行

題目描述 小 a 和小 b 決定利用假期外出旅行,他們將想去的城市從 1 到 n 編號,且編號較小的 城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 i 的海拔高度為 hi,城市 i 和城市 j 之間的距離 d i,j 恰好是這兩個城市海拔高度之差的絕對值,即 d i,j hi ...