JZOJ 5415. 【NOIP2017提高A组集训10.22】公交运输
Description
城市中有一條長度為n的道路,每隔1的長度有一個公交車站,編號從0到n,學校在0號車站的位置。其中每個公交車站(除了n號車站)有兩個屬性ci和vi,代表從這個公交車站出發的公交車的性質。ci代表這個從i出發的公交車,相鄰兩個??空局g的距離。vi表示每坐1站的花費。
注意,一輛公交車出發后會向n號車站的方向行進。同時,一名乘客只能從起點站上車,但可以從任意??空鞠萝?。校慶志愿者小Z為了幫助校友查詢有關城市交通費用的問題,想知道從0號車站(也就是學校)出發,到達每個公交車站的最小花費,于是他找到了你。
Input
輸入的第一行有兩個整數,n和maxc。
之后的n行,每行兩個整數,分別表示0到n-1號車站的c和v.
Output
輸出一行n個整數,其中第i個整數代表從0號車站到i號車站的最小花費,若不能從0號車站到達i號車站,則在i號車站的位置輸出-1。
Sample Input
輸入1:
1 1
1 1
輸入2:
9 5
2 5
5 2
5 14
1 18
4 13
3 17
1 16
1 7
5 4
Sample Output
輸出1:
1
輸出2:
-1 5 -1 10 -1 15 19 20 33
Data Constraint
對于30%的數據滿足,1<=n<=5000
對于60%的數據滿足,1<=n<=10^5
對于另20%的數據滿足,maxc=1
對于100%的數據滿足,1<=n<=10^6,1<=maxc<=10,1<=ci<=maxc,1<=vi<=1000
數據存在梯度。
Hint
樣例1說明:從0號車站坐1站地,到達1號車站,花費為1,可以發現這是從0號車站到1號車站的最小花費。
Solution
設 F[i] 表示第 i 個點的最優答案,那么顯然可以想到:F[i]=min{F[j]+i?jc[j]?v[j]}
但是這樣DP的時間復雜度是 O(N2) ,顯然不能AC。
看到后面的一串表達式像斜率的形式,但是由于轉移距離 c[j] 的限制不能直接斜率優化。
于是我們想到分類討論:按照 c 的值和 i mod c 的值維護 maxc?maxc 一個上凸包,
用單調棧存儲即可。時間復雜度為 O(N) 。
Code
#include<cstdio> #include<vector> using namespace std; const int N=1e6+1,inf=1e9; vector<int>s[11][10]; int f[N],c[N],v[N]; inline int read() {int X=0,w=1; char ch=0;while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();return X*w; } inline void write(int x) {if(x<0) putchar('-'),x=-x;if(x>9) write(x/10);putchar(x%10+'0'); } inline int min(int x,int y) {return x<y?x:y; } inline double get(int x,int y) {if(v[x]==v[y]) return inf;return (double)(f[x]-f[y]-v[x]*(x/c[x])+v[y]*(y/c[y]))/(v[y]-v[x]); } inline int calc(int x,int y) {return f[y]+(x-y)/c[y]*v[y]; } int main() {int n=read(),mc=read();for(int i=1;i<=n;i++) c[i-1]=read(),v[i-1]=read(),f[i]=inf;for(int i=0;i<n;i++){int x=c[i],y=i%c[i];while(!s[x][y].empty() && v[i]<=v[s[x][y][s[x][y].size()-1]]) s[x][y].pop_back();while(s[x][y].size()>1 &&get(i,s[x][y][s[x][y].size()-1])>=get(s[x][y][s[x][y].size()-2],s[x][y][s[x][y].size()-1])) s[x][y].pop_back();s[x][y].push_back(i);for(int j=1;j<=mc;j++){y=(i+1)%j;while(s[j][y].size()>1 &&calc(i+1,s[j][y][s[j][y].size()-1])>=calc(i+1,s[j][y][s[j][y].size()-2])) s[j][y].pop_back();if(!s[j][y].empty()) f[i+1]=min(f[i+1],calc(i+1,s[j][y][s[j][y].size()-1]));}}for(int i=1;i<=n;i++) write(f[i]==inf?-1:f[i]),putchar(' ');return 0; }總結
以上是生活随笔為你收集整理的JZOJ 5415. 【NOIP2017提高A组集训10.22】公交运输的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JZOJ 5407. 【NOIP2017
- 下一篇: JZOJ 5417. 【NOIP2017