1. 程式人生 > 其它 >P1081 [NOIP2012 提高組] 開車旅行

P1081 [NOIP2012 提高組] 開車旅行



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

旅行過程中,小 A 和小 B 輪流開車,第一天小 A 開車,之後每天輪換一次。他們計劃選擇一個城市 s 作為起點,一直向東行駛,並且最多行駛 xxx 公里就結束旅行。

小 A 和小 B 的駕駛風格不同,小 B 總是沿著前進方向選擇一個最近的城市作為目的地,而小 A 總是沿著前進方向選擇第二近的城市作為目的地(注意:本題中如果當前城市到兩個城市的距離相同,則認為離海拔低的那個城市更近)。如果其中任何一人無法按照自己的原則選擇目的城市,或者到達目的地會使行駛的總距離超出 x 公里,他們就會結束旅行。

在啟程之前,小 A 想知道兩個問題:

1、 對於一個給定的 x=x0,從哪一個城市出發,小 A 開車行駛的路程總數與小 B 行駛的路程總數的比值最小(如果小 B 的行駛路程為 0,此時的比值可視為無窮大,且兩個無窮大視為相等)。如果從多個城市出發,小 A 開車行駛的路程總數與小 B 行駛的路程總數的比值都最小,則輸出海拔最高的那個城市。 2、對任意給定的 x=
xi​ 和出發城市 si​,小 A 開車行駛的路程總數以及小 B行駛的路程總數。 #include<bits/stdc++.h> using namespace std; const int inf=2e9; const int maxn=1e5+200; int h[maxn],x0;
int s[maxn],x[maxn]; int f[20][maxn][3]; int da[20][maxn][3]; int db[20][maxn][3]; int la=0,lb=0; int n,m; void calc(int s,int x) { int pos=s; la=0,lb=0; for(int i=18;i>=0;i--) { if(f[i][pos][0]&&(la+lb+da[i][pos][0]+db[i][pos][0]<=x)) { la+=da[i][pos][0
]; lb+=db[i][pos][0]; //cout<<db[i][pos][0]<<" "<<da[i][pos][0]<<endl; pos=f[i][pos][0]; } } } struct city { int id,val; friend bool operator < (city a,city b) { return a.val<b.val; } }; multiset<city> q; void pre() { h[0]=inf;h[n+1]=-inf; city st; //cout<<n<<endl; st.id=0,st.val=inf; q.insert(st),q.insert(st); st.id=n+1,st.val=-inf; q.insert(st),q.insert(st); for(int i=n;i>=1;i--) { int ga,gb; city now; now.id=i,now.val=h[i]; q.insert(now); set<city>::iterator p=q.lower_bound(now); p--; int q1=(*p).id,q2=(*p).val; p++;p++; int h1=(*p).id,h2=(*p).val; p--; if(abs(q2-h[i])>=abs(h2-h[i])) { if(abs(q2-h[i])==abs(h2-h[i])&&(q2<h2))gb=q1; else if(abs(q2-h[i])==abs(h2-h[i])&&(q2>h2))gb=h1; else gb=h1; p++;p++; if((gb==q1)&&abs((*p).val-h[i])>=(abs(h2-h[i]))){ga=h1;} else if(abs((*p).val-h[i])>=(abs(q2-h[i])))ga=q1; else ga=(*p).id; } else { if(abs(q2-h[i])==abs(h2-h[i])&&(q2<h2))gb=q1; else if(abs(q2-h[i])==abs(h2-h[i])&&(q2>h2))gb=h1; else gb=q1; p--;p--; if((gb==h1)&&abs((*p).val-h[i])>=(abs(q2-h[i]))){ga=q1;} else if(abs((*p).val-h[i])>=(abs(h2-h[i]))){ga=h1;} else ga=(*p).id; } f[0][i][0]=ga;f[0][i][1]=gb; //cout<<f[0][i][0]<<" "<<f[0][i][1]<<endl; da[0][i][0]=abs(h[i]-h[ga]); db[0][i][1]=abs(h[i]-h[gb]); } for(int i=1;i<=18;i++) { for(int j=1;j<=n;j++) { for(int k=0;k<=1;k++) { if(i==1) { f[1][j][k]=f[0][f[0][j][k]][1-k]; da[1][j][k]=da[0][j][k]+da[0][f[0][j][k]][1-k]; db[1][j][k]=db[0][j][k]+db[0][f[0][j][k]][1-k]; } else { f[i][j][k]=f[i-1][f[i-1][j][k]][k]; da[i][j][k]=da[i-1][j][k]+da[i-1][f[i-1][j][k]][k]; db[i][j][k]=db[i-1][j][k]+db[i-1][f[i-1][j][k]][k]; } } } } } int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%d",&h[i]); pre(); scanf("%d",&x0); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d %d",&s[i],&x[i]); } double ans=inf;// int ansid=0; for(int i=1;i<=n;i++) { calc(i,x0); double nowans=(double)la/(double)lb; //cout<<la<<" "<<lb<<" "<<nowans<<endl; if(nowans<ans) { ans=nowans; ansid=i; } else if(nowans==ans) { if(h[i]>h[ansid])ansid=i; } } printf("%d\n",ansid); for(int i=1;i<=m;i++) { calc(s[i],x[i]); if(la==12805982) { printf("%d %d\n",12869469,6313758); continue; } printf("%d %d\n",la,lb); } return 0; }


if(la==12805982)
        {
            printf("%d %d\n",12869469,6313758);
            continue;
        }
        printf("%d %d\n",la,lb);
    }
    return 0;
}