小 和小 決定利用假期外出旅行,他們將想去的城市從 $1 $ 到 編號,且編號較小的城市在編號較大的城市的西邊,已知各個城市的海拔高度互不相同,記城市 的海拔高度爲,城市 和城市 之間的距離 恰好是這兩個城市海拔高度之差的絕對值,即 。
旅行過程中,小 和小 輪流開車,第一天小 開車,之後每天輪換一次。他們計劃選擇一個城市 作爲起點,一直向東行駛,並且最多行駛 公里就結束旅行。
小 和小 的駕駛風格不同,小 總是沿着前進方向選擇一個最近的城市作爲目的地,而小 總是沿着前進方向選擇第二近的城市作爲目的地(注意:本題中如果當前城市到兩個城市的距離相同,則認爲離海拔低的那個城市更近)。如果其中任何一人無法按照自己的原則選擇目的城市,或者到達目的地會使行駛的總距離超出 公里,他們就會結束旅行。
在啓程之前,小 想知道兩個問題:
對於一個給定的 ,從哪一個城市出發,小 開車行駛的路程總數與小 行駛的路程總數的比值最小(如果小 的行駛路程爲 ,此時的比值可視爲無窮大,且兩個無窮大視爲相等)。如果從多個城市出發,小 開車行駛的路程總數與小 行駛的路程總數的比值都最小,則輸出海拔最高的那個城市。
對任意給定的 和出發城市 ,小 開車行駛的路程總數以及小 行駛
的路程總數。
假設這個並非是必須向東行駛。
我們可以對 數組進行排序。
則排好序的第 個城市,第 近的城市和第 進的城市,一定在 這些城市當中。
那麼向東行駛怎麼處理呢?
我們可以用這樣一個思想:
首先,想讓第 個城市沒有向東行的限制,可以直接把 這 個城市刪掉。
這樣就可以解除向東行的限制。
我們可以試着用一個鏈表,來模擬這個東西。
priority_queue<pair<int,pair<int,int> > >q;
read(n);
for(int i=1;i<=n;i++){
read(m[i].h);
m[i].id=i;
}sort(m+1,m+n+1,cmp);
for(int i=1;i<=n;i++){
id[m[i].id]=i;
pre[i]=i-1;lat[i]=i+1;
}
for(int i=1;i<=n;i++){
while(q.size())q.pop();
int x=id[i];
int p1=pre[x],p2=pre[pre[x]],l1=lat[x],l2=lat[lat[x]];
bool pb1=true,pb2=true,lb1=true,lb2=true;
if(p1<=0)pb1=false;
else if(p2<=0)pb2=false;
if(l1>n)lb1=false;
else if(l2>n)lb2=false;
if(pb1){
q.push(make_pair(-abs(m[x].h-m[p1].h),make_pair(-m[p1].h,p1)));
if(pb2)q.push(make_pair(-abs(m[x].h-m[p2].h),make_pair(-m[p2].h,p2)));
}
if(lb1){
q.push(make_pair(-abs(m[x].h-m[l1].h),make_pair(-m[l1].h,l1)));
if(lb2)q.push(make_pair(-abs(m[x].h-m[l2].h),make_pair(-m[l2].h,l2)));
}
if(q.size())fi[i]=m[q.top().second.second].id;
if(q.size())q.pop();
if(q.size())se[i]=m[q.top().second.second].id;
lat[p1]=lat[x];pre[l1]=pre[x];
}
我這裏是用一個堆, 了 個可能的數,然後搞。
之後就直接倍增,這裏就不詳細講了
#include <bits/stdc++.h>
using namespace std;
template<typename T>inline void read(T &FF){
T RR=1;FF=0;char CH=getchar();
for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
FF*=RR;
}
const int MAXN=1e5+10;
struct node{
int h,id;
}m[MAXN];
int n,id[MAXN],pre[MAXN],lat[MAXN],fi[MAXN],se[MAXN],f[MAXN][25],a[MAXN][25],b[MAXN][25],A,B;
double Min=10000000000;
priority_queue<pair<int,pair<int,int> > >q;
bool cmp(node a,node b){
return a.h<b.h;
}
void work(int x,int x1){
A=0;B=0;
for(int j=19;j>=0;j--)
if(f[x1][j]&&(A+B+a[x1][j]+b[x1][j])<=x){
A+=a[x1][j];
B+=b[x1][j];
x1=f[x1][j];
}
if(se[x1]&&A+B+a[x1][0]<=x)A+=a[x1][0];
}
int main(){
read(n);
for(int i=1;i<=n;i++){
read(m[i].h);
m[i].id=i;
}sort(m+1,m+n+1,cmp);
for(int i=1;i<=n;i++){
id[m[i].id]=i;
pre[i]=i-1;lat[i]=i+1;
}
for(int i=1;i<=n;i++){
while(q.size())q.pop();
int x=id[i];
int p1=pre[x],p2=pre[pre[x]],l1=lat[x],l2=lat[lat[x]];
bool pb1=true,pb2=true,lb1=true,lb2=true;
if(p1<=0)pb1=false;
else if(p2<=0)pb2=false;
if(l1>n)lb1=false;
else if(l2>n)lb2=false;
if(pb1){
q.push(make_pair(-abs(m[x].h-m[p1].h),make_pair(-m[p1].h,p1)));
if(pb2)q.push(make_pair(-abs(m[x].h-m[p2].h),make_pair(-m[p2].h,p2)));
}
if(lb1){
q.push(make_pair(-abs(m[x].h-m[l1].h),make_pair(-m[l1].h,l1)));
if(lb2)q.push(make_pair(-abs(m[x].h-m[l2].h),make_pair(-m[l2].h,l2)));
}
if(q.size())fi[i]=m[q.top().second.second].id;
if(q.size())q.pop();
if(q.size())se[i]=m[q.top().second.second].id;
lat[p1]=lat[x];pre[l1]=pre[x];
}
for(int i=1;i<=n;i++){
f[i][0]=fi[se[i]];
a[i][0]=abs(m[id[i]].h-m[id[se[i]]].h);
b[i][0]=abs(m[id[fi[se[i]]]].h-m[id[se[i]]].h);
}
for(int j=1;j<=20;j++)
for(int i=1;i<=n;i++){
f[i][j]=f[f[i][j-1]][j-1];
a[i][j]=a[i][j-1]+a[f[i][j-1]][j-1];
b[i][j]=b[i][j-1]+b[f[i][j-1]][j-1];
}
int x,ans;read(x);
for(int i=1;i<=n;i++){
work(x,i);
if(B&&1.0*A/B<Min){
Min=1.0*A/B;
ans=i;
}
}cout<<ans<<endl;
int T;for(read(T);T--;){
int j,x;read(j);read(x);
work(x,j);
printf("%d %d\n",A,B);
}
return 0;
}