省選模擬 1 11

2022-09-14 10:30:10 字數 4821 閱讀 3060

t1 的暴力 dp 寫了很久,心裡也覺得不太穩,但過了大樣例就沒管,結果爆 0 了。。。還是不能有僥倖心理

t2 想到了正解結論但寫了個暴力維護沒過樣例,以為假了,而且時間也不太夠

t3 想到了正解結論的弱化版,還是缺少觀察

首先是時間分配不太合理,在感知到 t2 可做的情況下還花了大量時間做 t1,不太划算

其次是有些浮躁,能想出一些東西但不夠深入

「沒啥了,沒啥,就挺自卑的,挺難受的,感覺啥也不是——pyt」

序列 \(a\) 出現多次算多次,那麼可以列舉出現位置算有多少個彩色序列,直接算很難,考慮算補集(有多少個非彩色序列包含 \(a\))。

直接 dp 需要狀壓(判斷 \(a\) 是否出現),減小狀態的關鍵是觀察 \(a\) 在不同情況下的性質,分類討論採用不同 dp 方式

具體做法官方題解很詳細了

「至少 \(20\%\) 結點有趣」顯然是用來隨機化找到乙個有趣點的

建 dfs 樹,如果樹中存在前向邊/橫叉邊那麼根一定不合法,否則樹上都是返祖邊,考慮其他點是否合法

結論:一點合法的充要條件是其子樹中的返祖邊僅有一條指向子樹外(該點祖先),且該點祖先合法

正確性顯然

實現方法貌似有很多

設每個向量選了 \(k_i\) 次,那麼合法的 \(\,\cdots,k_\}\) 一定唯一對應乙個凸包,因此本質是數序列。同時可以發現,凸包橫座標極差為 \(\sum_>0}k_x_\)

樸素做法是列舉每個 \(k_i\) 或狀壓當前 \(\sum k_x_\)。

類似「noip2021 t2」,考慮按位 dp 來湊出 \(k\)。列舉 \(k_i\) 在當前位的取值,結合上一位的進製可以得到 \(\sum_>0}k_x_\),合法的條件是 \(\sum_>0}k_x_,\sum_<0}k_x_\) 當前位相同。

為了保證 \(\sum_>0}k_x_\le m\),還需要記當前及以後位是否 \(\le m\)

這個 trick 大概對於 \(\sum^k_x_=m\),\(n,x\) 很小而 \(m\) 很大的題都適用

沒啥大問題,唯一的遺憾就是最後 30min 沒有玩 t1 的 \(k\le3\) 而是去打 t3 的表

結論:乙個劃分是守序的,等價於 \(\forall k\in(1,n],\exists i,\min a_

必要性:若不滿足,則可將 \(a\) 根據 \(\max\) 與 \(k\) 的大小劃分為兩個集合 \(s,t\),則有 \(\forall i\in s,j\in t,\max a_,一定不能相鄰,無法成環

充分性:考慮歸納構造。先將 \(a\) 以 \(\min\) 排序,設前 \(i\) 個 \(a\) 已排列成環,根據結論一定存在 \(j\le i,\min a_<\min a_<\max a_\),又有 \(\min a_<\min a_\),可以將 \(a_\) 放在 \(a_j\) 之前

發現我們只關心每個 \(a\) 的 \(\min,\max\),且不關心其具體大小,可以以此 dp。從小到大列舉每個數 \(i\),考慮其放到那個集合中。

設 \(f[i,j,k]\) 為前 \(i\) 個數,分成 \(j\) 個集合,其中 \(k\) 個的 \(\max\ge i\),轉移有四種:

做法很多:分塊,莫隊,線段樹+bitset。標算是 \(\text\log\) 的

顯然難點在於單點修改、區間乘積的 \(\varphi\),即 \(\prod(1-\frac)\)。(每個質因子只貢獻一次,所以本質是數顏色)

修改本質是刪除和插入,而刪除可以看作插入的逆元,分別考慮每個質數的插入。使用set維護集合 \(\\}\)(即質因子包含 \(p\) 的位置集合)

這類問題的經典想法是容斥。記 \(w=1-\frac\),在 \(i\) 位置插入時,求出其前驅 \(pre\),後繼 \(suf\),然後在 \((pre,suf),(i,i)\) 上乘 \(w\),\((pre,i),(i,suf)\) 上乘 \(\frac\),這樣查詢 \([l,r]\) 時只需要查正方形 \((l,l)\sim(r,r)\) 的權值積,這是乙個樸素的三維偏序

時間複雜度為 \(o(n\log^)\)。但 \(40000\) 內的數最多有 \(6\) 個不同質因子,每次修改需要在平面上加入 \(6\) 個點,因此常數很大

記 \(mn(i)=\min(a_,a_)\),\(mx\) 同理

先考慮 60pts 的費用流做法:先統計所有的 \(|a_-a_|\),將 \(b_i\) 插到 \(a_i\) 前的貢獻為:\(\max(2b_-2mn(i),2mx(i)-2b_,0)\),可以將 \(a,b\) 的值分開計算。建兩個點代表 \(\max\,\min\\),這樣只需要將 \(a,b\) 分別與這兩點連邊,邊數降到 \(o(n)\) 級別

進一步發現這張圖性質很好,可以模擬費用流

結論:若要反悔,一定是將一條原來與最大值匹配的線段改為匹配當前最小值,並給被奪取匹配的最大值另找一條線段

證明:顯然具體的匹配不重要,只需要考慮線段是與最大值還是最小值匹配。因此反悔時一定是將原來匹配最大值的改為匹配最小值,且被奪取匹配的最大值不會繼續反悔,否則在它加入時就已經反悔了

另一種考慮角度是觀察網路流的圖,只能從另乙個代表最值的點退 \(1\) 單位流量

開四個堆儲存最值,陣列記錄匹配情況即可

感覺這兩天簽到完了就沒啥幹的,想不動也寫不動。以後如果發現簽到題就先寫完拍上,然後扔掉去做原計畫。還有就是學藝不精,看到點仙人掌沒想到邊雙樹

考場上打錶出了 \(ans(n,k)=\text(n,ans(n-1,k-1))\),但沒意識到答案就是 \(\text(1\cdots n)\)。。。 證明

那麼只需要維護字尾的 \(\text\),可以使用主席樹+棧來維護質因子

有樹剖+線段樹和 lct 兩種做法,不難想,但確實難調。考場上遇到這種題一定要慎重抉擇是否寫

寫完一題就交一下,別最後發現什麼問題導致手忙腳亂的

這題的 \(k\le2\) 和 \(w_=1\) 都是原題,做的時候也沒想如何擴充套件,於是 gg 了

k++,這樣距離為 \(k\) 的點對可以同時選

正解考慮 dp,設 \(f[u,d]\) 為子樹 \(u\) 中所選的點距 \(u\) 至少 \(d\) 的最大價值,轉移時列舉距 \(u\) 為 \(d\) 的點出自那個子樹:

這是長剖優化的經典形式,寫的時候注意定義中蘊含了字尾 \(\max\),需要仔細維護

dp 部分

ll dp(int u,int d) 

rfor(i,h[v],0) f[u][i] = max(g[i], dp(u,i+1));

}}

外校的老哥確實『講的好』

最初的想法時列舉點對算貢獻,但這樣需要考慮兩點到其 lca 路徑上所有點,複雜度無法接受。不過據此可以得到正解的想法:在 lca 處統計貢獻

設 \(f[u,v]\) 為子樹 \(u,v\) 中點歸併成的拓撲序中逆序對數的期望,\(g[u,v]\) 為點 \(u\) 比子樹 \(v\) 中點大的個數,有

\[ans=\sum_f(u,v) \\

f(u,v)=\frac(g[u,v]+\sum_f(x,v))\frac(g[v,u]+\sum_f(x,u))

\]統計答案為列舉 lca(\(w\)),則其兩子樹 \(u,v\) 中的點都是 \(w\),一起計算

\(f\) 的轉移為先列舉 \(u,v\) 哪個在前,然後合併其子樹(子樹合併順序無關,因此不需要考慮相互的影響)

記得預處理逆元

考了好幾次拉格朗日插值了,卻都沒能看出來,當初學習的時候大概只是記住了公式,但對其使用情況並不熟悉,需要引起注意

記 \(p_=\lfloor\frac\rfloor,q_=ic-b\)(\(q_i\) 即為滿足 \(p_=i\) 的最小 \(x\))

\[a_=a+\sum_^f(i)a_}

\]考慮算後面的 \(\sum\):

\[\sum_^f(i)\sum_^}f(j)a_} \\

=\sum_^}f(j)a_}\sum_}^f(i) \\

=\sum_^}f(j)(sf(n)-sf(q_-1))a_}

\]如果設 \(g(i)=f(i)(sf(n)-sf(q_-1))\),那麼就是乙個遞迴的形式

每次 \(g\) 的次數會加 \(m+1\),遞迴次數為 \(\log\),使用 \(o(n)\) 拉格朗日插值複雜度為 \(o(m^\log^n)\)

實現上可以遞迴,每次傳遞 \(g\) 的點值即可

使用多項式科技可以做到 \(o(m\log^n\log^(m\log n))\)

顯然通過 \(n-1\) 次詢問可以得到每個深度上有哪些點,然後考慮逐層計算(為當前深度的點在上一層找父親)

從上一層的點中隨機乙個點作為基準,詢問這兩層的點到基準的距離,不難發現父親與兒子的距離差一定為 \(1\),可以據此分治(建議畫圖,本質是從基準開始跳父親,分離出其兄**樹中的點並遞迴該子樹)

詢問複雜度為 \(t(2^)=\sum_^t(2^)+2^\),據 chy 證明為 \(o(n\log n)\),實際表現約為 \(10n\)

codeconst int n = 1e5+5;

int dep[n],dis[n],fa[n][17];

vi ver[n];

void init(int u,int v)

int lca(int u,int v)

int dist(int x,int y)

int visit(int, int);

int v(int x,int y)

void mysort(int x,vi::iterator l,vi::iterator r) {

for(auto i = l; i != r; ++i) dis[*i] = v(x,*i);

sort(l,r,(const int &x,const int &y){return dis[x]

省選模擬 19 09 11

ps.博主趁資訊課摸魚考的暴零模擬 看門人憑感覺就知道是長鏈剖分,將路徑查分一下,dis u di sv 2 dis lc adis u dis v 2 dis disu disv 2 disl ca 維護fu,if fu,i 表示u的子樹,深度為 i 的點的 dis disdi s最大值 考慮如何...

省選模擬96

容易發現當 k 3 時無解。然後容易證明當 k 3 時,只有 m 3 才是有解的。然後直接做不好做,考慮欽定然後容斥出合法方案。對於 k 3 列舉乙個點,然後計算另乙個的方案數。其他情況類似,欽定滿足條件的角,然後容斥。然後對於每乙個 o n 的式子用組合恒等式大力化簡就可以做到 o 1 了。考慮每...

省選模擬86

首先考慮基礎的dp定義,那麼發現轉移需要的係數只和dp是奇數的點的個數有關,所以將這個東西記錄在dp狀態中就行了。然後推一下dp轉移,發現轉移係數和奇數的點的個數沒有關係,只與是否存在這樣的點有關,所以用01來記錄就可以了。考慮用總方案減去不合法的方案,也就是1號點能到達的點和2號點能到達的點沒有交...