小 a 和小 b 決定利用假期外出旅行,他們將想去的城市從 1 到 n 編號,且編號較小的城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 i 的海拔高度為hi,城市 i 和城市 j 之間的距離 d[i,j]恰好是這兩個城市海拔高度之差的絕對值,即d[i,j] = |hi− hj|。 旅行過程中,小 a 和小 b 輪流開車,第一天小 a 開車,之後每天輪換一次。他們計畫選擇乙個城市 s 作為起點,一直向東行駛,並且最多行駛 x 公里就結束旅行。小 a 和小 b的駕駛風格不同,小 b 總是沿著前進方向選擇乙個最近的城市作為目的地,而小 a 總是沿著前進方向選擇第二近的城市作為目的地(注意:本題中如果當前城市到兩個城市的距離相同,則認為離海拔低的那個城市更近)。如果其中任何一人無法按照自己的原則選擇目的城市,或者到達目的地會使行駛的總距離超出 x 公里,他們就會結束旅行。
在啟程之前,小 a 想知道兩個問題:
對於乙個給定的 x=x0,從哪乙個城市出發,小 a 開車行駛的路程總數與小 b 行駛的路程總數的比值最小(如果小 b 的行駛路程為 0,此時的比值可視為無窮大,且兩個無窮大視為相等)。如果從多個城市出發,小 a 開車行駛的路程總數與小 b 行駛的路程總數的比值都最小,則輸出海拔最高的那個城市。
對任意給定的 x=xi和出發城市 si,小 a 開車行駛的路程總數以及小 b 行駛的路程
總數。第一行包含乙個整數 n,表示城市的數目。
第二行有 n 個整數,每兩個整數之間用乙個空格隔開,依次表示城市 1 到城市 n 的海拔高度,即 h1,h2,……,hn,且每個 hi都是不同的。
第三行包含乙個整數 x0。
第四行為乙個整數 m,表示給定 m 組 si和 xi。
接下來的 m 行,每行包含 2 個整數 si和 xi,表示從城市 si出發,最多行駛 xi公里。
輸出共 m+1 行。
第一行包含乙個整數 s0,表示對於給定的 x0,從編號為 s0的城市出發,小 a 開車行駛的路程總數與小 b 行駛的路程總數的比值最小。
接下來的 m 行,每行包含 2 個整數,之間用乙個空格隔開,依次表示在給定的 si和
xi下小 a 行駛的里程總數和小 b 行駛的里程總數。
對於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≤100,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 互不相同。
神tm全世界就我乙個被卡空間了?
倍增優化dp。
這題難就難在預處理。
首先預處理出 a 和 b 每個人從乙個城市出發的目標是哪個城市。可以用平衡樹找乙個點的前驅和後繼,或者雙向鍊錶。我當然選擇了最偷懶的 set。(upd:這裡如果用 set 的話有可能迭代器一直加或者減導致越界,又懶得判斷,索性用了 multiset)
然後預處理出 f[i][j][k(0/1)] 表示第 k 個人從第 i 個城市出發走 2^j 天到達的城市,同時也更新 dp[x(0/1)][i][j][k(0/1)] 表示第 k 個人從第 i 個城市出發走 2^j 天後第 x 個人走了多少路程。
最後預處理完暴力跑幾遍就行了。
//by youngneal
#include#include
#include
#include
#include
#define n 100005
#define inf 1234567890000
using
namespace
std;
intn;
intstarx;
intheight[n];
int f[n][20][5
];int dp1[n][20][3],dp2[n][20][3
];struct
node
};multiset
s;void calc(int s,int &a,int &b,int
x) }
}signed main()
else
f[i][
0][0]=goa;
f[i][
0][1]=gob;
dp1[i][
0][0]=abs(height[i]-height[goa]);
dp1[i][
1][0]=dp1[i][0][0
]; dp2[i][
0][1]=abs(height[i]-height[gob]);
dp2[i][
1][1]=dp2[i][0][1
];
//while(1);
}//0->a 1->b dp[i][j][k][p]->from i drive 2^j first is k distance p go
for(int i=1;i<=n;i++)
for(int k=2;k<=18;k++)
}scanf("%d
",&starx);
double ans=inf*10.0
;
intidx;
for(int i=1;i<=n;i++)
else
}printf(
"%d\n
",idx);
intt;
scanf("%d
",&t);
while(t--)
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 ...
NOIP2012 開車旅行
小 a 和小 b 決定利用假期外出旅行,他們將想去的城市從 1 到 n 編號,且編號較小的城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 i 的海拔高度為 h i 城市 i 和城市 j 之間的距離 d i,j 恰好是這兩個城市海拔高度之差的絕對值,即 d h i h j 旅行過程...