P5468 P6302 NOI2019 回家路線

2022-02-27 08:42:28 字數 3127 閱讀 9778

原題p5468,洛谷加強版p6302,loj3156

聽說原題是用腳造的資料,所以可能無法把**的鍋都測出來,所以還是去加強版吧

做了好長時間,主要是原版得分玄學,有的時候把**乙個地方改錯甚至得了更多的分(當時同時還存在其它的錯)?/jk,然後加強版又被卡常/kk

斜率優化dp+vector 維護凸包+堆維護還沒放入凸包的點

首先想怎麼設計狀態,一開始想的是 \(f_\) 表示時間 \(i\),剛達到車站 \(j\),的最小煩躁值

但這樣顯然會產生很多無用狀態,就是可能在某乙個時間 \(i\),沒有到車站 \(j\) 的車,那這乙個狀態就是無用的

所以改進一下,設 \(f_i\) 為坐完編號為 \(i\) 的車時,的最小煩躁值,這樣可以由車的編號確定到達時間了

然後對於所有 \(y_i=n\) 的車,\(\min\\) 即為答案

然後考慮怎麼轉移,\(f_i\) 由 \(f_j\) 轉移而來的條件是,\(q_j\le p_i,y_j=x_i\),所以可以吧防塵寫成這樣:

\[f_i=\min_\

\]那直接暴力轉移就是 \(o(n^2)\) 了,能得 \(70\),再加上有 \(20\) 的特殊限制的部分分,那誰還為了最後十分寫dp優化啊

還是要寫的,看著有乙個平方項,展開的話就有一項是和 \(i,j\) 都有關,那就能想到斜率優化了

其實感覺好多斜率優化的題都是用這麼乙個平方來創造那個 \(kx\),就是和 \(i,j\) 都有關的項(比如經典的玩具裝箱)

那就先不考慮限制條件,化簡式子:

\[f_i=f_j+ap_i^2+aq_j^2-2ap_iq_j+bp_i-bq_j+c

\]\[f_j+aq_j^2-bq_j=2ap_iq_j+(f_i-ap_i^2-bp_i-c)

\]也就是根據斜率優化常見的套路,把等號左邊和 \(j\) 有關的設為 \(y\),括號裡和 \(i\) 有關的(包括常數)設為 \(b\),且 \(k=2ap_i,x=q_j\)

所以維護乙個下凸包,最小化斜率即可

這時的把限制條件考慮回來

\(y_j=x_i\) 這個,只要對每個點都維護乙個凸包,\(f_i\) 從第 \(x_i\) 個凸包轉移,轉移結束,就加入到第 \(y_i\) 個凸包裡

這個 \(q_j\le p_i\) 稍微有點麻煩,因為 \(p_j,所以 \(p_j,那我們應該把所有車按 \(p\) 公升序排序來處理

但這個 \(p_j只是說,如果限制條件滿足,一定滿足他,但滿足他不一定滿足限制條件,一開始沒想清楚被這個坑了

所以此時再維護 \(n\) 個小根堆,用 \(q\) 排序,然後對於每個 \(i\),就把第 \(x_i\) 個堆中,所有 \(q_j\le p_i\) 的 \(j\) 都取出,並放入第 \(x_i\) 個 vector 維護成凸包

直到發現乙個點 \(q_j>p_i\) 了,那後面的 \(j\) 也都不符合要求,插入結束

如果滿足 \(q_j\le p_i\) 的 \(j\) 被插入凸包了,那由於 \(p\) 不減,後面的 \(i\) 肯定也滿足了這個條件了

然後 \(f_i\) 轉移完 \(i\) 就也不是直接插入凸包裡,而是插入對應的堆中,等他符合了相應條件再插入凸包

這也不妨是乙個更普適的思路,就是當用乙個資料結構維護點東西(比如凸包)來優化dp時,乙個狀態被轉移完,如果還不符合用它轉移其它狀態的要求,就先用另乙個資料結構存起來

還會發現這樣的話 \(k,x\) 都遞增了,可以用之間說的 vector 維護

這樣輕鬆過了原版和loj,但發現在加強版t成了40

於是愉快開始卡常,一開始是用set當堆來維護,然後換成優先佇列,稍微快了點,但還是40

然後又加了行編譯優化,依然40,好像沒啥用

也許是stl用的太多,不然一秒 \(10^6\) 的 \(o(m\log m)\) 應該挺好過吧,但因為是動態記憶體也不好避免stl

於是現學現賣fread,然後邊寫週末作業邊等到半夜,一交最大點997ms卡過,果然卡常的最好方式是等人少的時候提交

submit+=20

#pragma gcc optimize("ofast,no-stack-protector,unroll-loops,fast-math")

#include#include#include#include#include#include#include#define reg register

#define en std::puts("")

#define ll long long

namespace fread

#undef getc

}using namespace fread;

struct datat[1000006];

int n,m;

ll a,b,c;

ll f[1000005];

ll x[1000001],y[1000001];

std::vectorq[1000001];

struct cmp//按 q 的公升序

};std::priority_queue<_insert>insert[1000001];

inline int cmp(data a,data b)

//inline ll x(int i)

//inline ll y(int i)

inline void insert(int i)

q[t[i].x].push_back(j);

size--;insert[t[i].x].pop();

j=insert[t[i].x].top().i; }}

inline void pop(int i)

}int main());

} x[i]=t[i].q;y[i]=f[i]+a*t[i].q*t[i].q-b*t[i].q;

// if(f[i]<0)

} ll ans=1e18;

for(reg int i=1;i<=m;i++)if(t[i].y==n) ans=min(ans,f[i]+t[i].q);

// for(reg int i=1;i<=m;i++) std::printf("%lld\n",f[i]);

std::printf("%lld",ans);

return 0;

}

P2254 NOI2005 瑰麗華爾茲

單調佇列優化線性dp 單調佇列中只需儲存下標 只能優化最內層迴圈 dp c 1 x y dp c 1 x que tl dis x,y,x,que tl 時才將隊尾元素出隊 而不僅僅是dp c 1 x y dp c 1 x que tl 即 用隊中所存下標對應狀態對當前狀態的貢獻為依據選擇是否留在隊...

P2048 NOI2010 超級鋼琴

小z是乙個小有名氣的鋼琴家,最近c博士送給了小z一架超級鋼琴,小z希望能夠用這架鋼琴創作出世界上最美妙的 這架超級鋼琴可以彈奏出n個音符,編號為1至n。第i個音符的美妙度為ai,其中ai可正可負。乙個 超級和弦 由若干個編號連續的音符組成,包含的音符個數不少於l且不多於r。我們定義超級和弦的美妙度為...

P4174 NOI2006 最大獲利

洛谷傳送門 題意 有n個中轉站建造方案,每個中轉站有乙個建造的費用,有m個使用者群,每個使用者群能帶來一定的收益,但是每個使用者群都會指定兩個中轉站必須建造,問最大可能收益 思路 最大權閉合圖 定義 在有向圖中,每個點有乙個權值,取乙個點集,使得沒有乙個點有向外指的邊,這樣的權值最大的點集。可以發現...