【NOI2019】回家路线【无后效性dp状态设计】【斜率优化】
傳送門
題意:給定MMM個班車,每個班車pip_ipi?時刻從xix_ixi?發(fā)車qiq_iqi?到達(dá)yiy_iyi?,等車ttt時間花費(fèi)代價At2+Bt+CAt^2+Bt+CAt2+Bt+C,在ttt時刻到達(dá)花費(fèi)ttt的代價,求從111到NNN的最小花費(fèi)。
1≤N≤100000,1≤M≤2000001 \leq N \leq 100000,1 \leq M \leq 2000001≤N≤100000,1≤M≤200000
顯然是個dp
容易想到一個二維dp,第一維記當(dāng)前位置,第二維記時間
由于數(shù)據(jù)范圍很大,所以需要優(yōu)化掉一維
仔細(xì)想想為什么需要兩維?
因?yàn)槲恢檬怯泻笮缘?#xff0c;需要用時間節(jié)點(diǎn)來標(biāo)記。
而時間是一去不復(fù)返的,是個天然的無后效性狀態(tài)。
所以可以考慮按時間dp,先假設(shè)沒有位置限制。
此題對時間唯一的限制是不能沖突,所以按照班車的時間段dp。
假設(shè)可以瞬間移動,不計(jì)最終代價,設(shè)坐上第iii輛班車的最小代價是fif_ifi?
fi=min?qj≤pi{fj+A(pi?qj)2+B(pi?qj)+C}f_i=\min_{q_j \leq p_i}\{f_j+A(p_i-q_j)^2+B(p_i-q_j)+C\}fi?=qj?≤pi?min?{fj?+A(pi??qj?)2+B(pi??qj?)+C}
盲猜斜率優(yōu)化
假設(shè)決策j,kj,kj,k有j<kj<kj<k,kkk比jjj優(yōu)
即
fk+A(pi?qj)2+B(pi?qj)+C≤fj+A(pi?qj)2+B(pi?qj)+Cf_k+A(p_i-q_j)^2+B(p_i-q_j)+C\leq f_j+A(p_i-q_j)^2+B(p_i-q_j)+Cfk?+A(pi??qj?)2+B(pi??qj?)+C≤fj?+A(pi??qj?)2+B(pi??qj?)+C
fk+A(pi?qj)2+B(pi?qj)≤fj+A(pi?qj)2+B(pi?qj)f_k+A(p_i-q_j)^2+B(p_i-q_j)\leq f_j+A(p_i-q_j)^2+B(p_i-q_j)fk?+A(pi??qj?)2+B(pi??qj?)≤fj?+A(pi??qj?)2+B(pi??qj?)
fk+Api2?2Apiqk+qk2+Bpi?Bqk≤fj+Api2?2Apiqj+qj2+Bpi?Bqjf_k+Ap_i^2-2Ap_iq_k+q_k^2+Bp_i-Bq_k \leq f_j+Ap_i^2-2Ap_iq_j+q_j^2+Bp_i-Bq_jfk?+Api2??2Api?qk?+qk2?+Bpi??Bqk?≤fj?+Api2??2Api?qj?+qj2?+Bpi??Bqj?
fk?2Apiqk+qk2?Bqk≤fj?2Apiqj+qj2?Bqjf_k-2Ap_iq_k+q_k^2-Bq_k \leq f_j-2Ap_iq_j+q_j^2-Bq_jfk??2Api?qk?+qk2??Bqk?≤fj??2Api?qj?+qj2??Bqj?
2Api+B≥fk+qk2?fj?qj2qk?qj2Ap_i+B \geq\frac{f_k+q_k^2-f_j-q_j^2}{q_k-q_j}2Api?+B≥qk??qj?fk?+qk2??fj??qj2??
發(fā)現(xiàn)ppp和qqq分開了(其實(shí)不分開也能做的說)
所以可以把出發(fā)和到達(dá)拆開,分別排序,雙指針維護(hù)
考慮位置限制
對于一個pip_ipi?,只有yj=xiy_j=x_iyj?=xi?的qjq_jqj?會更新答案
所以可以用vector存NNN個凸殼
遇到出發(fā)在對應(yīng)結(jié)點(diǎn)的凸殼上算出fff。因?yàn)槟X袋抽了寫了個二分。
遇到到達(dá)在對應(yīng)結(jié)點(diǎn)用之前的fff更新凸殼
最后能到達(dá)NNN的算答案。
當(dāng)時做的時候式子推反了,然后二分的時候凸殼算反了就負(fù)負(fù)得正A了……
我可能是個傻子
#include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <algorithm> #include <vector> #define MAXN 200005 using namespace std; struct event{int idx,pos,tim;}st[MAXN],ed[MAXN]; inline bool cmp(const event& a,const event& b){return a.tim<b.tim;} int n,m,A,B,C; int f[MAXN]; inline int Y(const int& i){return f[ed[i].idx]+ed[i].tim*ed[i].tim;} inline int calc(const int& i,const int& j) {int d=st[i].tim-ed[j].tim;return f[ed[j].idx]+A*d*d+B*d+C; } vector<int> v[MAXN]; int vis[MAXN]; int main() {scanf("%d%d%d%d%d",&n,&m,&A,&B,&C);for (int i=1;i<=m;i++){int x,y,p,q;scanf("%d%d%d%d",&x,&y,&p,&q);st[i]=(event){i,x,p};ed[i]=(event){i,y,q};}memset(f,0x7f,sizeof(f));sort(st+1,st+m+1,cmp);sort(ed+1,ed+m+1,cmp);int now=0;for (int i=1;i<=m;i++){while (now<m&&ed[now+1].tim<=st[i].tim){++now;if (vis[ed[now].idx]) continue;vector<int>& cur=v[ed[now].pos];while (cur.size()>1&&(Y(now)-Y(cur[cur.size()-1]))*(ed[cur[cur.size()-1]].tim-ed[cur[cur.size()-2]].tim)<=((Y(cur[cur.size()-1])-Y(cur[cur.size()-2]))*(ed[now].tim-ed[cur[cur.size()-1]].tim))) cur.pop_back();cur.push_back(now);}if (st[i].pos==1) f[st[i].idx]=A*st[i].tim*st[i].tim+B*st[i].tim+C;else{vector<int>& cur=v[st[i].pos];if (cur.size()){int l=0,r=cur.size()-1,mid;while (l<r){mid=(l+r)>>1;if ((2*A*st[i].tim+B)*(ed[cur[mid+1]].tim-ed[cur[mid]].tim)<=Y(cur[mid+1])-Y(cur[mid])) r=mid;else l=mid+1;}f[st[i].idx]=calc(i,cur[l]);}else vis[st[i].idx]=true;}}int ans=f[0];for (int i=1;i<=m;i++) if (ed[i].pos==n) ans=min(ans,f[ed[i].idx]+ed[i].tim);printf("%d\n",ans);return 0; }總結(jié)
以上是默认站点為你收集整理的【NOI2019】回家路线【无后效性dp状态设计】【斜率优化】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 头右边一阵一阵的疼,是不是颈椎引起的?
- 下一篇: 【CF1189D】Add on a Tr