只需要口胡CF題就行啦!(
從昨天起口胡 CF 按照洛谷透過人數排序的題單
這期我們來口胡 CF2100 Part 1 吧 ~
目錄導航:
- CF 2000Ct 輯
- CF 2100Ct 輯
CF208E Blood Cousins
給定樹上節點 \(a\) 和距離 \(p\),求有多少 \(b\) 節點滿足 \(a\) 與 \(b\) 的 \(p\) 級祖先相同。
可以點分樹。更簡單的做法是啟發式合併。
題解還有線段樹合併的做法的,感覺很有趣。
CF343D Water Tree
樹。 \(m\) 次操作。操作有 \(3\) 種:
1. 將點 \(u\) 和其子樹上的所有節點的權值改為 \(1\)。
2. 將點 \(u\) 到 \(1\) 的路徑上的所有節點的權值改為 \(0\)。
3. 詢問點 \(u\) 的權值。\(1\le n,m\le 5\times 10^5\)。
重鏈剖分+線段樹板題
看看題解吧,什麼,\(O(n\log n)\) ?!
題解給了一道前置題目,那我們就先做這道前置題目吧:
[P2936 USACO09JAN] Total Flow S [展開]
\(\le 52\) 個節點,每個節點之間可能有多條水管。串聯水管取流量最小的作為合併後的水管的流量。並聯水管取流量之和為合併後的水管的流量。求 \(A\) 點到 \(Z\) 點的流量。
不就是 Floyd
嗎,為什麼是藍題。看題解吧。
哦,原來還可以是網路流啊(
不過看評論區好像是樹上差分的原題被吞了,所以現在的前置題目和本題沒有一點關係/憤怒
對於本題:
看了題解程式碼,我驚為天人!!!
題解開了兩顆線段樹, T1
記錄該節點被改成 \(1\) 的最晚時間, T2
記錄該節點是 \(2\) 操作鏈上最底端的最晚時間。
scanf("%d %d",&op,&x);
if(op == 1)t1[dfn[x]:dfn[x]+size[x]-1]+=i;
else if(op == 2)t2[dfn[x]]+=i;
對於查詢, \(1\) 操作查詢該節點 \(1\) 操作的最晚時間, \(2\) 操作查詢子樹內最晚的操作時間。
else if(op == 3)printf("%d\n",t1[dfn[x]:dfn[x]]>t2[dfn[x]:dfn[x] + size[x] - 1]);
CF1187E Tree Painting
樹。一個點被刪除只能當這個點是第一個被刪除或者有一個相鄰的被刪除點。刪除時記錄該點所在聯通塊大小 \(S_i\) ,找到一種刪除點的順序來最大化 \(\displaystyle\sum S_i\)。
好像是 dp ,但是不會。
看一下提示吧:
刪除了第一個點後,剩下的就不影響權值了
噢噢噢噢好有意思,寫一下程式碼吧
展開程式碼
#include<bits/stdc++.h>
using namespace std;
#define ff(i,l,r) for(auto i=(l);(i)<=(r);++i)
#define fi(l,r) ff(i,l,r)
#define lowbit(x) ((x)&(-(x)))
#define ll long long
#define ul unsigned ll
#define ui unsigned int
#define P 998244353
#define N 200005
#define M 400005
ll ans,f[N],g[N];
int siz[N],tot,fir[N],nxt[M],to[M],n;
void add(int x,int y){
nxt[++tot]=fir[x];
fir[x]=tot;
to[tot]=y;
}
void dfs1(int x,int fa){
siz[x]=1;
for(int e=fir[x];e;e=nxt[e]){
int u=to[e];
if(u==fa)continue;
dfs1(u,x);
siz[x]+=siz[u];
f[x]+=f[u];
f[x]+=siz[u];
}
}
void dfs2(int x,int fa){
ans=max(ans,f[x]+g[x]+n);
for(int e=fir[x];e;e=nxt[e]){
int u=to[e];
if(u==fa)continue;
g[u]=f[x]-f[u]-siz[u]+g[x]+n-siz[u];
dfs2(u,x);
}
}
int main(){
scanf("%d",&n);
fi(2,n){
int x,y;
scanf("%d %d",&x,&y);
add(x,y);
add(y,x);
}
dfs1(1,0);
dfs2(1,0);
printf("%lld\n",ans);
return 0;
}
一遍過,帥!
CF656D Rosetta Problem
題目描述是亂碼,就不放了。
這道題太難了,根本不會做。看題解吧。
題解看完還是不懂,做不了一點/doge
CF620E New Year Tree
給出一棵 \(n\) 個節點的樹,根節點為 \(1\)。每個節點上有一種顏色 \(c_i\)。\(m\) 次操作。操作有兩種:
1 u c
:將以 \(u\) 為根的子樹上的所有節點的顏色改為 \(c\)。2 u
:詢問以 \(u\) 為根的子樹上的所有節點的顏色數量。\(1\le n,m\le 4\times 10^5\),\(1\le c_i,c\le 60\)。
注意到顏色範圍很小,開60個樹狀陣列 (91MB
) 就行了。
看看題解吧。
oh,原來可以狀壓。我小丑了。
CF372C Watching Fireworks is Fun
一個城鎮有 \(n\) 個區域,從左到右編號為 \(1\sim n\),每個區域之間距離 \(1\) 個單位距離。
有 \(m\) 個煙火要放,給定放的地點 \(a_i\),時間 \(t_i\),如果你當時在區域 \(x\),那麼你可以獲得 \(b_i - \vert a_i - x\vert\) 的開心值。
你每個單位時間可以移動不超過 \(d\) 個單位距離。
你的初始位置是任意的(初始時刻為 \(1\)),求你透過移動能獲取到的最大的開心值。
\(1\le n\le 1.5\times 10^5\),\(1 \le m \le 300\),\(1\le d,a_i\le n\),\(1\le t_i,b_i\le 10^9\)。
感覺是 \(O(nm)\) 的。
\(f[t][i] = \Big\downarrow\left\{\big\downarrow_{j=a_i-d}^{a_i}\left(f[t-1][j] - j\right) - b_i + a_i,\big\downarrow_{j=a_i+d}^{n}\left(f[t-1][j] + j\right) + b_i - a_i\right\}\)
可以用單調棧。 \(O(nm)\)。
CF837D Round Subset
\(n\) 個數 \(a_{1 \sim n}\) 中選 \(k\) 個讓乘積的字尾 \(0\) 最多。
\(1 \le k \le n \le 200 , 1 \le a_i \le 10^{18}\)
這是一個 minmax 問題,注意到 \(n\) 很小,因數 \(2\) 和 \(5\) 出現的也很少( \(60\) 個 \(2\) )。記狀態 \((i,j,x,y)\) 代表前 \(i\) 個數裡選 \(j\) 個數,\(2\) 的個數為 \(x\) ,\(5\) 的個數為 \(y\) 。那麼就可以設 \(f[i][j][y] = \max{x}\) 。複雜度 \(O(n^2\log_5^{1 \text{e} 18})=2\,060\,174\) 。
CF519E A and B and Lecture Rooms
樹上詢問兩個點 \(x,y\) ,求到 \(x,y\) 距離相等的點的數量。 \(m\) 次詢問。
\(1 \le m,n \le 10^5\)
設 \(x\) 和 \(y\) 的路徑中點為 \(z\) 。如果 \(z\) 不存在( \(dis(x,y)\) 為奇數),那麼數量為零。
否則記與 \(z\) 相鄰的點為 \(u\) ,答案即為 \(x,y\) 所不在的 \(u\) 樹大小之和 \(+ z\) 點。
CF609E Minimum spanning tree for each edge
給定一個無向圖,求出必須包括 \(i\) 號邊時的最小生成樹。 \(i:1\sim n\);
\(1\le n,m \le 2\times 10^5\)
簡單題,略。
CF1207F Remainder Problem
給你一個長度為 \(500000\) 的序列,初值為 \(0\) ,你要完成 \(q\) 次操作,操作有如下兩種:
1 x y
: 將下標為 \(x\) 的位置的值加上 \(y\)2 x y
: 詢問所有下標模 \(x\) 的結果為 \(y\) 的位置的值之和運算元 \(\leqslant500000\)
根號分治:
對於大於 \(\sqrt{5\text{e}5}=707\) 的數,\(2\) 操作的時候暴力統計。
對於小於等於 \(707\) 的數, \(1\) 操作的時候暴力維護。