【IOI2014】Rail 題解
Statement
【IOI2014】Rail - Problem - Universal Online Judge (uoj.ac)
Solution
互動題。。。
不妨探究一下所謂“最短路”會長成什麼樣子(圖略醜)
圖中,從紅色點是目標點,藍色路徑,發現紅色點和 \(0\) 點的關係只有這四種。
容易發現 \(dis_{i,j}=dis_{j,i}\) ,即順序不影響長度
至此,我們對題目有了一定認識,考慮求解
可以想到先把所有點到 \(0\) 的最短路都求出來
顯然,這個時候,距離 \(0\) 最近的點必然是在 \(0\) 右邊的第一個型別 \(D\) 的點,設這個點叫做 \(P\)
一個車站有這樣幾個屬性需要我們去確定:1.在 \(0\)
先考慮如何確定左右
觀察上面四種情況,發現一個站點在 \(0\) 的左邊必定是繞了一個點 且 繞過了 \(0\)
那麼不妨求出所有點到 \(P\) 的最短路,此時
如果 \(dis[0][i]==dis[0][p]+dis[p][i]\)
\(\qquad if\) \(dis[p][i]>dis[0][p]\) ,那麼是情況 3,在左邊
\(\qquad else\) \(dis[p][i]<dis[0][p]\) ,那麼是情況 2 ,可以直接確定 \(i\) 的位置在 \(dis[0][p]-dis[p][i]\),型別 \(C\)
否則,在右邊
再考慮如何判斷型別,我們現在已經判斷了 \([0,P]\)
對於在左邊的點,先按 \(dis[i][0]\) 從小到大排序,假設全部都是型別 \(C\)
假設我們現在求解到了 \(now\) ,上一個確定的型別 \(C\) 在 \(bef\)
\(now\) 有兩種情況,這兩種情況對於 \(P\) 而言,距離是相同的
考慮問一下 \(getDistance(bef,now)\) ,會得到紅色/藍色路徑長度
那麼 \(now\) 究竟在哪裡顯然取決於 \(mid\) 位置是型別 \(C/D\)
當 \(mid\) 型別為 \(C\) 的時候,\(now\) 型別為 \(D\) (藍色路徑)
當 \(mid\) 型別為 \(D\) 的時候,\(now\)
考慮 \(mid\) 這個位置具體在哪裡: \((getDistance(bef,now)+dis[bef][P]-dis[now][P])/2\)
(注意上面的 \(now\) 是假設型別為 \(C\) 的時候的 \(now\) )
左邊處理完了,右邊同理
這樣我們 \(getDistance\) 的次數就是最開始 \(2\times(n-1)\) 次加上這裡 \(n-2\) 次
Code
#include "rail.h"
#include<bits/stdc++.h>
using namespace std;
const int N = 5e4+5;
const int M = 1e6+5;
int R,mn=1e9,bef,len,now;
int sta[2][N],ct[2],dis[N][2],vis[M];;
bool cmp(int a,int b){return dis[a][0]<dis[b][0];}
void findLocation(int n,int fi,int location[],int stype[]){
location[0]=fi,stype[0]=vis[location[0]]=1;
if(n==1)return;
for(int i=1;i<n;++i){
dis[i][0]=getDistance(0,i);
if(dis[i][0]<mn)mn=dis[i][0],R=i;
}
location[R]=location[0]+mn,stype[R]=2,vis[location[R]]=2;
for(int i=1;i<n;++i){
if(i==R)continue;
dis[i][1]=getDistance(i,R);
if(dis[i][1]+mn==dis[i][0]){
if(dis[i][1]<mn)location[i]=location[R]-dis[i][1],vis[location[i]]=stype[i]=1;
else sta[0][++ct[0]]=i;
} else sta[1][++ct[1]]=i;
}
sort(sta[0]+1,sta[0]+ct[0]+1,cmp);
sort(sta[1]+1,sta[1]+ct[1]+1,cmp);
bef=0;
for(int i=1;i<=ct[0];++i){
now=sta[0][i];
len=(dis[bef][1]-dis[now][1]+getDistance(bef,now))/2;
if(vis[location[bef]+len]==1)
stype[now]=2,location[now]=2*(location[bef]+len)+dis[now][1]-location[R];
else bef=now,stype[now]=1,location[now]=location[R]-dis[now][1];
vis[location[now]]=stype[now];
}
bef=R;
for(int i=1;i<=ct[1];++i){
now=sta[1][i];
len=(dis[bef][0]-dis[now][0]+getDistance(bef,now))/2;
if(vis[location[bef]-len]==2)
stype[now]=1,location[now]=2*(location[bef]-len)-dis[now][0]-location[0];
else bef=now,stype[now]=2,location[now]=location[0]+dis[now][0];
vis[location[now]]=stype[now];
}
}