2024.9.16
重新定義飲料為一大杯冰沙
胃:這把生死局(指抿一口就開始起反應...)
早上就不停反嘔,下午整這一出真是笑嘻了
T1 不相鄰集合
以為貪心假的,結果對了
就是對新加的數看看有沒有左鄰右舍被取過,沒有就計入答案
code
T2 線段樹
暴力\(20\)
考慮到線段樹開點方式,點編號之和肯定可以寫成一次函式,具體的,設\(f_{n,x}\)表示根為\(x\),有\(n\)個葉子是的和,那麼\(f_{n,x} = k_n \times x + b_n\)
然後有關係
代入表示式可得:
可以記憶化處理
然後正常跑查詢,如果找到\([l,r]\)在詢問區間內,貢獻就是\(k_{r - l + 1} \times id + b_{r - l + 1}\)
byd mid沒開ll耗掉不少時間,被#define int long long教育力
code
T4 園藝
聽說資料很水最多列舉兩個拐點可過..
正解鞋油+單隊,感覺和之前掉餡餅的題很像
std1
std2
2024.9.22
菜死了
T1 自然數
下洗了,不會
先求出\([1,i]\)的mex,記為\(mex_i\),這個陣列單調不降。然後記錄\(a_i\)在後面第一次出現的位置\(nxt_i\)
接下來列舉左端點,每次移動都為刪掉一個\(x = a_l\),然後\(mex\)中大於\(x\)的值就會被改成\(x\),修改區間右端點就是\(nxt_l - 1\),左端點需要二分找第一個大於\(x\)的點,可以透過記錄最大值實現
然後上線段樹做區間修改,區間最值,區間求和即可
code
T2 錢倉
手膜膜錯辣
改過來後發現就是貪心,然後存在這樣一個點:該點後面的點的貨物不會運到該點前面
這個點滿足是最大子段和的起點(意思就是有足夠多的貨補給後面),由此處破環成鏈貪心即可
code
T3 遊戲
考場上拿無窮近似推了個賊像的式子,然而還是遺憾離場
std
code
T4 暴雨
暴力搜尋\(20\)
正解大炮,???
2024.9.28
T1 一般圖最小匹配
貪心可以有\(75\),但是考場上\(RE\)了一半多,後來使用魔法常數就\(OK\)了
damn
整潔大炮
先對\(a\)【排序,這樣後取相鄰的一定最優
定義\(dp_{i,j,0/1}\)表示到第\(i\)個數匹配了\(j\)對,並且第\(i\)個數沒有用上
則
使用滾動最佳化
code
T2 重定向
暴力列舉刪除位+填數有一半分
考慮到字典序最小,使用貪心
設\(minnum\)表示最小的未填數,\(minn_i\)表示\(a_i \sim a_n\)中最小的數
-
\(a_i = 0\)
如果minn_i < minnum,就要把\(minn_i\)刪掉往這裡放
-
\(a_i \neq 0\)
- \(a_i > a_{i + 1}\),則刪掉\(a_i\)更優
- \(a_{i + 1} = 0\),如果\(a_i > minnum\),那麼刪掉\(a_i\)更優
可以用優先佇列維護要填的數
- 注:在初始化優先佇列中,迴圈上界為\(n\)時會\(RE\),要改為\(n + 1\)(
不知道為甚莫)
code
T3 斯坦納樹
戳
T4 直徑
再戳
2024.10.2
障保齡而東之,回暴力於既倒
T2 肥胖
忘了可以從\(1\)走到其他點開吃,直接成\(10\)分,還都是\(-1\)...
為了成功,肯定想要把限制放大點
於是可以建最大生成樹
然後考慮選擇的邊中最小的,設為\((u,v,w)\),此時有一個結論:先吃完一個子樹再去吃另一個不劣於反覆橫跳
證明的話,考慮反覆橫跳吃的某一步肯定是吃了一棵子樹的最後一個然後跳到另一個,此時經過\((u,v,w)\)時的寬既有一棵子樹的所有糖還有另一棵子樹的一些糖,那還不如全吃完一棵,然後只經過一次\((u,v,w)\)到另一棵樹裡吃吃吃
然後考慮答案,設\(sum_u\)表示\(u\)字數內糖果總和,\(ans_u\)表示吃完\(u\)為根的子樹的最大初始體寬
假設從以\(u\)為根到以\(v\)為根,此時一個是要保證能過邊,即\(w \geqslant sum_u\),一個是要能吃完\(v\)樹,就是\(ans_v \geqslant sum_u\),兩答案取\(\min\),反之同理,\(u,v\)互換即可,最後兩個\(min\)取個\(max\)即可
注:由於一開始\(ans_i\)未求出,所以初始化成極大值
code
T3 分攤
看到分數嚇似了
實際上大概是這樣:只有兒子全滿了自己才開始存錢
設\(v\)為與當前點\(u\)有同樣父親的兄弟節點,那麼父親至少有\(x + \sum \min(sum_v,x)\)塊錢才能保證\(u\)拿到\(x\)塊錢,其中\(sum_v\)是\(v\)的子樹和
然後打\(log\)的話考慮倍增,但是略有不同
考慮到增量的維護,由於每一層都要和\(x\)比大小來產生貢獻,所以一口氣跳太多的話增量可能不能統一計算,會很麻煩
考慮一次跳躍,當上面的\(\min\)等於\(x\)時\(x\)會翻倍,此時可能計算方式不同,那麼到這個點之前的路徑的計算方式一樣,那麼另設一個\(g_{u,i}\)表示當\(u\)跳\(2^i\)級時,\(x \leqslant g_{u,i}\)時計算方式一樣,\(g\)可以在維護增量的時候一併求得
那麼就可以統一計算:二分\(\min\)的分界點,左邊計入子樹和,右邊計入若干個\(x\)
code + 註釋
T4 修路
暴力有\(27\)分
暴力時發現交點在圓內當且僅當兩個由端點形成的區間嚴格相交(不取等)
由此可以維護區間,打log可以使用線段樹一類物質
詳情
code
T1 戰爭
口胡可得\(31\)
std
2024.10.3
親手殺死整潔
T2 尋寶
看到傳送門單向直接ban掉並查集,事後發現可以在並查集上建單向邊跑暴力,畢竟最多\(100\)條邊...
code
T1 構造字串
手玩出\(30\)
正解就是相同的合併成塊,然後\((x_i + z_i,y_i + z_i)\)這兩處一定不同,連邊,非法就是塊內有邊
然後填數,塊內有位置填了直接染掉即可,否則求\(mex\)即可
code
T3 序列
官方題解:
容易發現這是一個與斜率有關的題目,這種題目通常透過維護凸包,或者李超樹維護
跨過\(p_i\)的區間容易轉化為:以\(p_i\)為右端點的最優+以\(p_{i}+1\)為左端點的最優
兩個問題同理,以右端點(\(p_i\))為例
設\(sa_i=\sum_{j=1}^i a_j\),\(sb_i=\sum_{j=1}^ib_j\)
最優即\(\max_{1\leq l\leq r}\{(sa_{r}-sa_{l-1})-k(sb_{r}-sb_{l-1})\}\)
即\(sa_r-k\cdot sb_{r} +\max_{0\leq l<r}\{ksb_{l}-sa_l\}\),離線之後李超樹維護直線即可
時間複雜度為\(O(n\log n)\),常數略大,空間複雜度為\(O(n)\)
往李超上套,就是把\(k\)當成\(x\)軸去搞
附李超講解
附李超板題
70分流產程式碼
T4 構樹
gugugugugugu~
2024.10.4
人死了一白天晚上才緩過來
T1 玩遊戲
貪心寫假了
不能只看挪動一位下左右誰最優,可能當前併入一個相對較大的數但是可以再並一個很小的負數,所以要用字首和分別把左右指標推到極小處,考慮到極小處不一定是端點,所以要反著從端點往極小處跑,同樣用字首和實現
code
T2 排列
std
code
T3 最短路
std太吊
將返回等價為建反邊後的前往,然後用dijkstra分別推進兩個支路,使用bitset助力維護
設\(dis_{x,y}\)表示從\(1\)走正邊到\(x\),走反邊到\(y\)(從\(y\)返回\(1\))的答案
code
T4 矩形
矩形重疊想到掃描線,但不會寫
std
code
2024.10.5
T1 送花
從左往右掃,貢獻是\([1 / lst_i + 1,i]\),然後掃到重複顏色時要刪貢獻,考慮到每次從\(1\)開始刪會重複,所以刪除區間是\([1 / lst_{lst_i},lst_i]\)
code
T2 星空
\(n \leqslant 300\)起手\(Floyd\)有\(45\)
考慮轉換座標系
將原座標系順時針旋轉\(45\)度,那麼原來的座標\((x,y)\)就會變成\((x - y,x + y)\),設為\((x',y')\)接著發現原座標系中的距離變成了\(\min(|\Delta x'|,|\Delta y'|)\),那麼距離為\(0\)的點就是\(x'\)或\(y'\)相同的點,使用並查集合並
最小距離的話就分別按\(x',y'\)排序,在\(x'/y'\)變化處作差比較並記錄所在塊的編號,那麼個數就是記錄的每對塊的\(size\)乘積的和,注意去重
code
T3 零一串
吊炸天
std
code
T4 Revive
線段樹 + \(dfn\) + 樹狀陣列...
std
2024.10.6
虛死了
不太想寫東西,扔\(std\)得了
std1
std2
T1b
code
T2 競賽圖
code
T3 糖果
code
T4 樹
code
2024.10.7
題目標題說得對
T1莓良心
糖,以為\(\mathfrak{Segment-Tree}\),把絕對值拆成\(max,min\)...
若干個區間相交的標誌:\(maxl <= minr\),此時所有數字沒貢獻
對於剩餘未相交區間,在\([minr,maxl]\)中間取數最優,此時所有數字貢獻為\(maxl - minr\),乘上區間數目
每次更新\(maxl,minr\)都會少兩個區間,求貢獻時還要算上他自己
code
T3 團不過
正難則反
設\(f_i\)表示有\(i\)堆石子時的非法數量,\(g_i\)表示總數
\(g_i\)很好求,就是全排列:\(g_i = A_{2^n-1}\)
考慮求\(f_i\)
既然要讓異或和為\(0\),那麼不妨直接讓第\(i\)堆石子數等於前\(i - 1\)堆石子數的異或和,此時要求前\(i - 1\)堆異或和不為\(0\),有\(g_{i - 1} - f_{i - 1}\)種,然後考慮重複的情況,第\(i\)堆和前面某一堆重複,那麼剩下的\(i - 2\)堆異或和就是\(0\),一共有\(i - 1\)堆,重複值的個數為\(2^n - 1 - (i - 2)\)(重複的兩堆和剩下的要互異),所以減去\((i - 1) \times f_{i - 2} \times (2^n - i + 1)\)
答案:\(g_n - f_n\)
T2 盡梨了
列舉\(b\)中\(1\)的個數,設為\(c\),設當前行\(1\)的個數為\(k\)
-
\(k < c\) : 有一些\(b\)的位置是\(1\),而矩陣中是\(0\),那麼\(a\)對應位置就要放\(0\)
-
\(k > c\) : 同理,\(a\)只能放\(1\)
-
\(k = c\) : 此時\(b\)可以全部接住\(1\),\(a\)可以隨便選
考慮計算
注意到\(k = c\)時要求所有\(k = c\)的行相同,判定稍後說,此時\(b\)唯一確定,所以方案數是\(2^{num}\)
如果不存在\(k = c\)的行,那麼\(b\)不確定,此時需要求出\(k < c\)至少需要多少個\(1\),以及\(k > c\)中至少需要多少個\(0\),後者可以求出至多有多少個\(1\),至多與至少的差是備選位置數量,然後可以選的有\(c - minn\)種,是個組合數
二者相互獨立
接下來考慮判定合法,考慮到\(b\)要接住所有\(k <= c\)的行的\(1\)和\(k >= c\)的\(0\),所以可以求並,那麼前後夾擊一下,\(pre\)求\(1\)的並,\(nxt\)求\(0\)的並,根據第二種情況可得,在\(c\)相同時,\(nxt\)為1的為\(pre\)必須為\(1\)而且\(nxt\)的\(1\)數量 \(\geqslant\) \(pre\)的\(1\)數量,由此判斷
code
T4 七負我
特殊性質(菊花圖)提示我們均分最優,實際上確實如此,證明可以看看,接著就是求最大團,可以使用\(BK\),就是一個搜尋
code
2024.10.8
簡單考了一場以替換月考
T1 雜湊結果空間小了 T2 Tarjan忘了 T3 貪心假了...
放個連結
2024.10.13
都想到一點但不多
T1 Hunter
其實很簡單,想複雜了
只有其他獵人在\(1\)號獵人之前死掉才會有\(1\)發的貢獻,而根據成正比可得獵人\(i\)在\(1\)前面死的機率為\(\frac{w_i}{w_i + w_1}\),累加即可
code
T2 Defence
一眼看出是最長連續\(0\)的長度,但是暴力都炸了
有坑:如\(00100\),需要\(4\)次,所以還有情況就是左右兩端連續最長\(0\)的和
使用線段樹合併,維護區間最大\(0\),左右端最多\(0\),在區間銜接處分討處理端點\(0\)的數量,因為可能出現整個區間全是\(0\)的情況
code
T3 Connect
一眼最大生成樹然後加回去一部分刪的邊,但是不好維護,因為可能加著加著就把兒子連起來成新路徑了
後來想到給\(1 \to n\)的“主鏈”上加東西,但是被題目搞懵了一下就下考了(輸出給的是刪掉邊和最小,但題目說的是剩餘邊最大和,我直接****)
使用狀壓,預處理出所有能往主鏈上掛的東西\(sum_S\),然後處理銜接邊\(cj_{S,i}\),之所以分開是因為掛的東西一點不在主鏈上,但是銜接的有一端在主鏈上,有一端在掛件裡。(\(S\)是點集,\(i\)是在主鏈上的一點)
然後\(dp\)的時候一邊延長主鏈一邊掛東西就行了
code
2024.10.14
byd被wx和hl雙重問候
T1score and rank
思路比較接近std,想到用堆維護
解釋:遇到負數就把他擺平,如果當前總和小於負數絕對值就直接將總和置為\(0\)
code
T2 HZOI大作戰
一眼倍增,不會維護...
解釋:等價於重定義\(f_{u,i}\)表示從\(u\)開始進行\(2^i\)次交換後到達的點,維護方式和lca基本一致
code
T4 gtm和joke的星球
斯坦納樹板子,原理就是最終連通圖必定是個樹,使用狀壓進行兩種操作:
1.合併:將有相同根的點集合並
2.換根:使用最短路更新點集的根使得邊權和儘可能的小
對每個點先進行第一步,再對整個點集進行第二步
code
T3 Delov的旅行
只能意會..
code
2024.10.15
T1 限速(speed)
比較簡單,建出最小生成樹,如果樹內最大邊大於\(k\),直接統計答案,否則列舉剩下的邊找更優的替換
code
T2 酒鬼 (drunkard)
把題審成部分分了,就只有部分分了(\(27pts\))
使用set維護,因為線索相互影響,要按時間排序再搞
發現\(p_i = 1\)時非常麻煩:擁有同一個\(min\)的\(p_i=1\)的時間滿足奇偶性相同,比如時刻為\(1,3,5,7\)的\(min\)都是\(1\),所以如果插入不同奇偶性時刻\(t'\),比如\(t = 4\)時在\(1\),那麼\(min\)會變成\(5\),因為單看\(4\),它的\(min\)是\(0\),不符合\(1,3\),但是還可以不走,所以\(min\)是\(5\),因此再用一個\(set\)單獨維護\(p_i = 1\)的時刻用於更新\(min\)。但還有一種情況:插入\(100\)的話\(min\)會變成\(7 + 1 = 8\),所以還要分類:如果\(t'\)大於最大,新的\(min\)就是最大值加一,否則就是\(t' + 1\),後者還要把比\(t' + 1\)小的值刪掉
但是還有一些線索會影響\(minn\)的奇偶性:時間上距離\(min\)最近的點。還是上面的\(1,3,5,7\),插入\(10,3\),會發現\(min\)不能是\(1\)了,但\(min = 8\)可以,所以還要改。而且最近點也要更新,一旦更新就還要去維護\(p_i = 1\)的時刻...
其他線索的維護就比較簡單:插入\(set\)後找前驅後繼,滿足以下兩點即可:
-
\(|\Delta T| >= dis\)
-
\(|\Delta T| - dis = 2k\)
後一條在判斷時間上距離\(min\)最近的點時也用到了
再加上特判有沒有前驅後繼等亂七八糟的細節 以及除錯,長度來到驚人的\(3k\)
code
T3 距離(distance)
亂搞\(40\)
列舉點對,形成的貢獻作用範圍是\(1 - lca\)的鏈,樹剖+線段樹維護即可有\(70\)
差點沒T2std長.....
T4 團隊選拔(selection)
2024.8.6 T4原題 戰績可查
2024.10.16
糖死了把檔案工工整整放到\(D\)盤忘交了...
T1 第一題
睡了導致什麼也沒有寫...
只要佔領全部葉子,其他點就佔完了,所以考慮怎麼佔完葉子
佔領一個葉子節點要麼從其他葉子轉移,要麼從根新派一個兵,對於前者事先按照深度排序,然後對於每個葉子決策兩種方式計算
code
T2 第二題
二分答案,然後遍歷所有點把差抹平到二分值以下,計算所需代價是否超過\(K\),\(40\)分抹一遍即可,要獲得\(90\)多分要抹十遍以上,最高\(95\)
考慮換一種方式:建圖遍歷,用類似\(Dij\)的方式搞,最佳化方案是先對所有點按權值排序(方式同\(dij\)),然後利用特殊性質用兩個佇列模擬\(Dij\)砍掉優先佇列的\(log\),執行一遍即可
code
T3 第三題
數位\(dp\),定義\(dp_{i,j,0/1,0/1}\)表示前\(i\)位一共有\(j\)個\(1\),卡/不卡下界(L),卡/不卡上界(R)
利用\(pair\),\(first\)存排名,\(second\)存和。考慮到只要有一位不卡上界後面的就都一定不卡,所以要按位與
考慮怎麼判斷卡不卡界限(由於對區間所有數排序所以初始狀態下一定卡)
對於上界,當前在第\(i\)位,如果這一位是\(0\),那沒辦法,因為前面一直卡著,選\(1\)的話就大於上界了,卡的狀態為\(1\)。相反,如果是\(1\),就有了不卡的機會,狀態為\(0\),發現剛好是異或的關係。下界剛好與上界相反,不用異或
更多細節看程式碼
code
T4 第四題
大炮
大腎tj
code
2024.10.17
T1 傳送 (teleport)
分別按照\(x,y\)排序,每次排完序後給相鄰邊連邊,最後跑最短路即可
code
T2 排列 (permutation)
考慮到最多隻有\(10\)的數可能會使得\(\gcd\)為\(k\),稱為關鍵數,不妨狀壓這十個數的狀態進行大炮
設\(dp_{i,s,j}\)表示當前放到第\(i\)位,關鍵數出現狀態為\(s\),最後一位放的是第\(j\)個關鍵數,\(0\)表示不放
列舉最後一位放什麼即可,如果上一位和這一位都是關鍵數則需要檢查\(\gcd\),其他情況直接轉移即可
code
T3 戰場模擬器 (simulator)
大資料結構模擬題
對於護甲和死亡,分類討論,如果當前區間有護甲/死亡人數就要遞迴到葉子,否則就是普通的區間修改,需要寫兩個函式,\(kill\)專門遞迴到葉子,\(attack\)/就只是普通修改,然後每次分左右區間都要分討一下來決定呼叫什麼函式,以此減小複雜度
code
T4 點亮 (light)
60ptscode
2024.10.19
2024.10.20
T1 Reverse
發現每次交換\(1\)可達的位置奇偶性相同,所以使用\(set\)分別儲存奇偶數,每次\(lowerbound\)找下限可達點,然後用\(bfs\)跳,並刪去被更新的點,這樣就能保證每個點只被更新一次。注意迭代器的尿性
code
T2 Silhouette
先對\(A,B\)排序,並不影響答案,然後令每一格 \(s = \min(A_i,B_j)\),發現相同\(s\)的個子形成矩形或者\(L\)型,使用容斥計算,具體原理戳
code
T3 Seat
一個結論是,對於任意一個人,他坐下時離最近的人的距離是一定的,那麼可以將所有人按照坐下時的距離分成若干層。對於距離為\(1\)的人特殊處理,因為此時怎麼選都是等機率的,對於其他距離的人,他們選擇座位時可能會存在長度為奇數的空區間以及長度為偶數的空區間,前者有一個備選位置,後者有兩個,所以需要大炮。定義\(dp_{i,j}\)表示已經坐了\(i\)個人,還剩\(j\)個偶區間的機率,根據當前人坐在奇區間內還是偶區間內來轉移
考慮到偶區間存在兩個備選位置,兩個位置是等價的,因此欽定一個人坐在某個位置,得到一系列答案,再對稱推出選另一個位置的答案即可
code
T4 萬豬拱塔
咕咕咕
2024.10.21
看到大家都不會做就放心了,純純墜機賽
T2沒判誤解掛了\(20\) QwQ
T1 島嶼
怎麼說呢。。。
code
T2 最短路
考慮建立最短路樹,以1為根節點。
如果把點\(i\)到它父親的邊斷了,為了到達 ,我們需要一條邊連線\(i\)的子樹內任意一節點和子樹外任意一節點
這樣需要列舉非樹邊,為了減少時間複雜度,不妨考慮一條非樹邊的貢獻
如圖,對於非樹邊\((u,v)\),可以轉化為\(dep_u + dep_v + w(u,v) - dep_k\),前三者都是定的,只有後者動,所以跳祖先更新\(ans\),可以使用並查集最佳化
code
T3 列表
第一個性質可以匯出第二個性質
定義雙指標 \(L,R\) 為出現的連續數字(即\(L,L + 1 ... R\)在\(S\)內出現),然後用性質2單調移動指標
根據性質2的等價轉換(區間內至少有\(R - L + 1 - (n - i)\)個數),可得\(num \geqslant R - L + 1 - (n - i)\)
這裡有個巧妙的轉化:對於一個位置,列舉到它時的\(i\)是一定的,所以一個位置的\(n - i\)是固定的,可以建樹時設好。那麼移動指標的時候維護\(num\)即可,比如\(R\)右移一位,然後\(R\)的貢獻就是給\([1,pos_R]\) + 1,這個區間是\(pos_R < N + 1\)的區間,\(> N + 1\)時應該是\([pos_R,2N + 1]\),但是\([N + 1 - i,N + 1 + i]\)是對稱的,又因為一個數最多產生一個貢獻,所以區間摺疊,這樣不管\(L,R\)怎麼變修改區間都是\([1,pos]\)
那麼每跳一次\(R\),用非法情況跳\(L\),即存在一個位置的值不滿足大於等於的關係,那麼如果最小值都滿足就合法了
code