Description
小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行駛的路程總數。
Input Format
第一行包含一個整數N,表示城市的數目。
第二行有N個整數,每兩個整數之間用一個空格隔開,依次表示城市1到城市N的海拔高度,即H1,H2,……,Hn,且每個Hi 都是不同的。
第三行包含一個整數X0。
第四行爲一個整數M,表示給定M組Si和Xi。
接下來的M行,每行包含2個整數Si 和Xi,表示從城市Si 出發,最多行駛Xi 公里。
Output Format
輸出共M+1行。
第一行包含一個整數S0,表示對於給定的X0,從編號爲S0的城市出發,小A開車行駛 的路程總數與小B行駛的路程總數的比值最小。
接下來的M行,每行包含2個整數,之間用一個空格隔開,依次表示在給定的Si 和Xi 下小A行駛的里程總數和小B行駛的里程總數。
Sample Input
樣例1 4 2 3 1 4 3 4 1 3 2 3 3 3 4 3 樣例2 10 4 5 6 1 2 3 7 8 9 10 7 10 1 7 2 7 3 7 4 7 5 7 6 7 7 7 8 7 9 7 10 7
Sample Output
樣例1 1 1 1 2 0 0 0 0 0 樣例2 2 3 2 2 4 2 1 2 4 5 1 5 1 2 1 2 0 0 0 0 0
Hint
對於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在每個點上出發到達的點(可以用各種數據結構處理),推薦比較高效的雙向鏈表(與noip2016初賽完善程序第一題一樣)
然後用倍增的做法f[i][j]記錄從i點出發AB輪換2^j輪後到達的地點(一輪是AB都開了一次車)
g[i][j][0]i到f[i][j]中A走的路程 g[i][j][1]記錄B的路程
對於第一問枚舉每一個起點倍增到不能走 最後比較一下就行了
第二問就直接從給定起點做倍增就行
詳見代碼
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
#include <vector>
#include <queue>
#include <map>
using namespace std;
long long g[100005][22][2],a,b,l,x;
double MIN,d;
int f[100005][22],get[100005][2],rank[100005],lef[100005],rig[100005];
struct info
{
long long h;
int num;
}city[100005],t[10];
int i,j,k,m,n,ans,s;
bool cmp(info x,info y) {return x.h<y.h;}
bool cmp1(info x,info y) {return (x.h<y.h || (x.h==y.h&&city[rank[x.num]].h<city[rank[y.num]].h));}
int main()
{
scanf("%d",&n);
for (i=1;i<=n;i++) scanf("%lld",&city[i].h),city[i].num=i;
sort(city+1,city+n+1,cmp);
for (i=1;i<=n;i++) rank[city[i].num]=i;
for (i=1;i<=n;i++) lef[i]=i-1,rig[i]=i+1;
city[0].h=city[n+1].h=1e9;
for (i=1;i<=n;i++)
{
k=0;
if (lef[rank[i]]!=0) t[++k]={abs(city[lef[rank[i]]].h-city[rank[i]].h),city[lef[rank[i]]].num};
if (rig[rank[i]]!=n+1) t[++k]={abs(city[rig[rank[i]]].h-city[rank[i]].h),city[rig[rank[i]]].num};
if (lef[lef[rank[i]]]!=0) t[++k]={abs(city[lef[lef[rank[i]]]].h-city[rank[i]].h),city[lef[lef[rank[i]]]].num};
if (rig[rig[rank[i]]]!=n+1) t[++k]={abs(city[rig[rig[rank[i]]]].h-city[rank[i]].h),city[rig[rig[rank[i]]]].num};
sort(t+1,t+k+1,cmp1);
rig[lef[rank[i]]]=rig[rank[i]];
lef[rig[rank[i]]]=lef[rank[i]];
if (k>0) get[i][1]=t[1].num;
if (k>1) get[i][0]=t[2].num;
}
for (i=1;i<=n;i++)
{
j=get[i][0];k=get[j][1];
if (k!=0) f[i][0]=k;else f[i][0]=i;
if (j!=0) g[i][0][0]=abs(city[rank[i]].h-city[rank[j]].h);else g[i][0][0]=1e15;
if (j!=0&&k!=0) g[i][0][1]=abs(city[rank[j]].h-city[rank[k]].h);else g[i][0][1]=1e15;
}
for (i=1;i<=20;i++)
for (j=1;j<=n;j++)
{
f[j][i]=f[f[j][i-1]][i-1];
if (g[j][i-1][0]==1e15||g[f[j][i-1]][i-1][0]==1e15) g[j][i][0]=1e15;
else g[j][i][0]=g[j][i-1][0]+g[f[j][i-1]][i-1][0];
if (g[j][i-1][1]==1e15||g[f[j][i-1]][i-1][1]==1e15) g[j][i][1]=1e15;
else g[j][i][1]=g[j][i-1][1]+g[f[j][i-1]][i-1][1];
}
scanf("%d",&x);MIN=1e16;
for (i=1;i<=n;i++)
{
l=0;k=i;a=0;b=0;
for (;l+g[k][0][0]+g[k][0][1]<=x;)
{
for (j=0;l+g[k][j][0]+g[k][j][1]<=x;j++);j--;
l+=g[k][j][0]+g[k][j][1];
a+=g[k][j][0];b+=g[k][j][1];
k=f[k][j];
}
if (l+g[k][0][0]<=x) a+=g[k][0][0];
if (b==0) d=1e15;else d=a/1.0/b;
if (d<MIN) ans=i,MIN=d;
}
printf("%d\n",ans);
for (scanf("%d",&m);m;m--)
{
scanf("%d%lld",&s,&x);
l=0;k=s;a=0;b=0;
for (;l+g[k][0][0]+g[k][0][1]<=x;)
{
for (j=0;l+g[k][j][0]+g[k][j][1]<=x;j++);j--;
l+=g[k][j][0]+g[k][j][1];
a+=g[k][j][0];b+=g[k][j][1];
k=f[k][j];
}
if (l+g[k][0][0]<=x) a+=g[k][0][0];
printf("%lld %lld\n",a,b);
}
}