現有 \(n\) 個線段,第 \(i\) 個線段長度為 \(l_i\),現最多可以切 \(k\) 刀,只能在整數字置切。要求最小化切完後所有線段的長度的平方和。又有 \(q\) 次操作,每次將 \(k\) 加一或減一,或者新加一段長為 \(l_i\) 的線段。每次問最小的平方和。\(n,q,l_i,k \le 10^5\)。保證答案不爆 long long首先 \(nqk\) 的揹包dp就不說了,反正正解和這沒啥關係。
注意不到平方和關於切的刀數是個下凸函式,或者說平方和的減少量這個東西關於切的刀數 \(k\) 是個減函式。於是可以費用流。
考慮一種網路流模型,將代價轉化為 $l_i^2 - $ 切 \(k\) 刀的收益。將收益拆成若干份,如果多給它一刀就會多獲得一些收益,跑最大費用可行流即可。正確性在於代價函式是下凸函式。這個費用流模型的優勢在於能更好地應對 \(k\) 的微小變化。
考慮模擬費用流。用乙個堆維護每個段當前能擴充套件出來的差分,再用乙個堆來維護已經選擇的那些差分。先撿收益大的 \(k\) 個差分作為初始答案。如果 \(k\) 加一,那麼從第乙個堆中找出最大的那個扔到第二個堆中並計入答案;如果 \(k\) 減一,那麼從第二個堆中選出最小的那個,放棄掉它。
對於新加入乙個段,我們可以直接暴力做,一直到它能擴充套件出來的差分小於已經選擇的最小的差分。我目前不會證複雜度(據說總共 \(o(nlogn)\) 次),但是能夠感性理解如果加乙個巨大的段而之前都非常小,我們會操作好多次,但是會把平均值拉大,以後就很難再操作那麼多次了。複雜度正確的主要原因是沒有刪除線段的操作。
總複雜度\(o(nlog^2n)\)。
關鍵**:
struct node
};inline ll calc(int x, int k)
inline ll calc(int x, int k)
multisetst, ts;
inline void init() );
for (register int i = 1; i <= k; ++i) ); }}
inline void add() );
}inline void del() );
--cnt[nd.cur];
ts.insert((node));
}inline void ins(int i) );
while ((*(--ts.end())).val > (*st.begin()).val) );
res -= nd.val;
ts.erase(ts.find((node)));
--cnt[nd.cur];
ts.insert((node));
}}
啟智樹提高組Day4T3 2的冪拆分
問把 n 拆分成2的冪的和的形式的方案數。注意拆分是無序的,即 2 0,2 2,2 1,2 0 和 2 0,2 0,2 1,2 2 是一種方案。n le 10 定義 s k n sum i k 部分下取整符號可能有遺漏。首先通過打表發現前幾項是 從0開始 1,1,2,2,4,4,6,6,10,10,...
啟智樹衝省隊組Day4T3 疏散
一棟大樓中 10 5 個人緊急疏散。大樓可以被視作網格圖 正檢視 有三個區域,由兩個寬為 1 的樓道隔開。走出樓道最下面即為離開。同一時刻乙個位置只能有乙個人。左右區域的人不能互相串。每個人每一秒能移動一格。問所有人離開所需的最小時間 這題正解比暴力好寫 一般貪心題都這樣 因此考場上沒想到貪心就很難...
NOIP2015提高組Day2T3 運輸計畫
傳送門 tips 如果兩個點的lca會被反覆用到,就可以拿乙個陣列存下來,避免反覆計算 analysis 又是一道好喵喵喵妙的題啊!樹上差分太棒了,簡直太厲害 不過首先我們得看出來這是一道二分可以解決的問題 然後問題就變成了怎麼check 看看gsj大佬怎麼說吧 code 注意常數因子帶來的程式效率...