水鏡
先考慮如何判定一個區間 \([l,r]\) 是否合法。
首先肯定存在一個分割點 \(mid\),使得 \([l,mid]\) 取 \(\min(h_i,2L-h_i)\),\((mid,r]\) 取 \(\max(h_i,2L-h_i)\)。
因此,記 \(p_i=\max(h_i,2L-h_i)\),則 \(p_i\) 需要先不升,再不降,並且只能在轉彎處有至多一對相等。
考慮其反面,也即不存在 \(p_{i-1}\leq p_i\geq p_{i+1}\)。對於每個 \(i\),這會匯出一個限制,為 \(L\notin[l,r]\),則判定一個區間是否合法只需要判定所有限制的並是否為全集即可。
又因為答案具有單調性,所以雙指標即可,判定全集有一萬種方法,時間複雜度 \(O(n\log n)\)。
線段樹
記線段樹 \(i\) 點的區間為 \([L_i,R_i)\)。
首先需要做一個轉化:對於線段樹上第 \(i\) 個點,如果我們知道其權值,就將 \(L_i\) 與 \(R_i\) 之間連一條邊,那麼 \([l_i,r_i)\) 的權值可以求出充要於 \(l_i\) 與 \(r_i\) 聯通。
把線段樹這個圖放到平面圖,會發現這是一個三角剖分類似物,因此對於第 \(i\) 個點,會有兩種情況:
- \(L_i\) 與 \(R_i\) 聯通,並且子樹內的聯通已經處理好了,子樹內到子樹外的聯通要求都和 \(L_i\) 聯通了。
- \(L_i\) 與 \(R_i\) 不聯通,並且存在一個 \(j\),使得子樹內所有沒有跨過 \(j\) 的聯通要求都滿足了,跨過 \(j\) 的聯通要求都一端和 \(L_i\) 聯通,一端和 \(R_i\) 聯通。
則我們將第一種記作 \(f_i\),第二種記作 \(dp_{i,j}\)。
\(f\) 與 \(f\) 之間的轉移是平凡的。
\(f\) 與 \(dp_i\) 的轉移不會改變 \(j\),因此是一個整體乘法。
\(dp_{u,x}\) 與 \(dp_{v,y}\) 的轉移需要要求跨過 \(x,y\) 的限制相同,也就是,\((x,y]\) 的要求都在 \(mid_i\) 滿足了。這個可以用 xor-hash 處理出等價類,然後在等價類之間轉移。
最後在 \(i\) 點的 \(dp_i\) 還要整體轉移到 \(f_i\)。
上述過程可以用線段樹合併維護,時間複雜度 \(O(n\log n)\)。
submission
眾生之門
首先任何一棵樹都可以構造出一個排列,滿足相鄰兩個點距離 \(\leq 3\),因此答案 \(\leq 3\),並且因為奇偶性是確定的,所以答案的最後一位是確定的。因此我們只需要確定答案的倒數第二位是啥就行了。
然後發現,除了菊花和 \(n\) 比較小的情況,最後的答案都是 \(\leq 1\) 的。
但是怎麼構造呢?答案是直接隨機(。因為你感受一下,你隨機一個排列,答案是均勻的,因此每次隨機交換兩個位置,然後計算新的貢獻即可。
submission
多方計算
首先我們有一個 \(n+m+\log n\) 的做法:在第 \(t\) 個時間將所有第 \(x\) 個人的第 \(y\) 位滿足 \(x+y+1=t\) 傳到下一個人,並把這一位清空,下一個人將這個值加到對應位置上並進位。這樣最多需要增加 \(\log n\) 位,可以獲得 \(49\) 分。
這個做法剛開始的時間非常浪費,後面的點都沒有傳遞資訊。我們考慮讓後面的點從 \(\log n\) 位開始傳遞資訊,傳遞一個三角形掉,這樣前面的進位就只有 \(\log \log n\) 個了,就可以做到 \(n+m+\log \log n\)。
這樣會比限制多一步,我們只需要讓開始的位從略小於 \(\log n\) 的位置開始。真正限制開始位置的是這一次加法的進位數量,我們將後面的三角形改成對很多平行四邊形同時做加法,就可以剛好進這個限制。
submission
投票遊戲
首先我們可以求出 \(f_i\) 表示 \(i\) 被票出時候 \(i\) 有幾票,這樣只需要比較 \((f_c,c)\) 和 \((f_d,d)\) 的大小即可。
首先考慮假設 \(i\) 的兒子的 \(f\) 都知道是啥了,\(f_i\) 怎麼求。維護一個變數 \(x=a_i+\sum\limits_{j\in son_i}b_j\), 當票數降到某個 \(f_j\) 的時候,將 \(x\) 減去 \(b_j\)。當 \(x\) 第一次和票數相同的時候就是 \(f_i\) 的值。這個值可以維護線段樹並線上段樹上二分快速得到。這樣就可以做隨機樹和菊花的情況。
然後一個自然的想法是輕重鏈剖分,並在重鏈上維護一些資訊。考慮 \(i\) 的重兒子 \(j\),記 \(i\) 去掉 \(j\) 之後的答案為 \(g_i\),則若 \(f_j<g_i\),則 \(f_i=g_i\),否則說明 \(b_j\) 最終一定會被去除,則線上段樹上改一下初始值之後再二分出另一種答案即可。
這樣我們每個點的答案可以用一個函式表示:
這顯然可以線段樹快速求一條鏈上的答案,然後輕邊暴力,這個題就做完了,時間複雜度 \(O(n\log n\log V)\),如果維護兒子的地方寫平衡樹就可以做到 \(O(n\log ^2n)\)。
submission
字串游戲
記 \(occ(i,j)\) 表示 \(s[i,j]\) 在 \(s[i,n]\) 中出現次數。
記 \(dp_i\) 表示 \(s[i,n]\) 的答案,顯然有 dp 是 \(f_i=\max\limits_{j=i+1}^{n}{occ(i,j-1)-f_j}\)。
這個 dp 是 \(O(n^2)\) 的,非常不牛。為了最佳化這個 dp,我們需要對這個 dp 觀察一些性質。
一個比較容易發現的性質是,如果 \(i<j\) 且 \(f_i\leq f_j\),則從 \(i\) 轉移一定不會比從 \(j\) 轉移更優,因為 \(occ(x,i)\geq occ(x,j)\),所以我們只需要保留 \(f_i\) 的字首最小值即可。
但這是不夠的。我們還可以注意到,如果在某次轉移中,\(i\) 的最優轉移點是 \(p_i\),則 \(p_i\) 之前的轉移點都沒有用了。這是因為對於兩個 \(occ(x,i),occ(x,j),i<j\),在 \(x\) 減一的過程中,\(occ(x,i)\) 的減小量 $\geq $ \(occ(x,j)\) 的減小量。
這樣就可以決策單調性,但是複雜度是兩個 log 的,過不了。
我們嘗試維護一個單調棧,棧內滿足 \(f\) 單調遞減。每次拿棧頂轉移到 \(i\),然後判斷 \(f_i\) 是否小於棧頂,如果小於就把棧頂彈了,否則退出。
這個做法的正確性在於,我們做完之後,記棧頂為 \(x\),一個非棧頂為 \(y\),需要證明 \(x\) 對 \(i\) 的轉移不劣於所有 \(y\) 對 \(i\) 的轉移。
反證,假設 \(f_i=occ(i,y-1)-f_y\),則有 \(f_i\leq occ(x,y-1)-f_y=f_x<f_i\),矛盾。因此 \(f_i\) 轉移完備。
所以我們只需要支援求 \(occ\) 即可,這個可以倍增+bit 實現,時間複雜度 \(O(n\log n)\)。
submission