給定一棵包含 \(n\) 個節點的樹,每條邊的長度皆為一,有 \(q\) 筆詢問,每次詢問任意兩節點之間的最低共同祖先
\((n, q \leq 10^6)\)
給定一棵包含 \(n\) 個節點的樹,每條邊的長度皆為一,有 \(q\) 筆詢問,每次詢問任意兩節點之間的路徑長度
\((n \leq 1.5 \cdot 10^4, q \leq 10^6)\)
給定一棵包含 \(n\) 個節點的樹,邊有邊權,有 \(q\) 筆詢問,每次詢問任意兩節點之間的路徑上最大連續和
\((n, q \leq 2 \cdot 10^5)\)
int p[maxn],link[maxn],top[maxn],d[maxn];
int getsize(int now=1,int pa=1,int depth=0){
p[now]=pa; d[now]=depth;
int siz=1;
pii maxx{0,0};
for(auto &to:e[now]){
if(to==pa) continue;
int t=getsize(to,now,depth+1);
siz+=t;
maxx=max(maxx,pii{to,t});
}
link[now]=maxx.second;
return siz;
}
void gettop(int now=1,int pa=1,int t=1){
top[now]=t;
if(link[now]!=0) gettop(link[now],now,t);
for(auto &to:e[now])
if(to!=pa&&to!=link[now])
gettop(to,now,to);
}
int lca(int a,int b){
while(top[a]!=top[b]){
if(d[top[a]]<d[top[b]]) swap(a,b);
a=p[top[a]];
}
if(d[a]<d[b]) return a;
return b;
}
樹上路徑問題 to 區間問題
按照gettop尋訪順序轉換成序列
int p[maxn],link[maxn],top[maxn],d[maxn],cnt[maxn];
int getsize(int now=1,int pa=1,int depth=0){
p[now]=pa; d[now]=depth;
int siz=1;
pii maxx{0,0};
for(auto &to:e[now]){
if(to==pa) continue;
int t=getsize(to,now,depth+1);
siz+=t;
maxx=max(maxx,pii{to,t});
}
link[now]=maxx.second;
return siz;
}
void gettop(int now,int pa,int t,int &cnt){
top[now]=t; ind[now]=cnt++;
if(link[now]!=0) gettop(link[now],now,t);
for(auto &to:e[now])
if(to!=pa&&to!=link[now])
gettop(to,now,to);
}
void gettop(int now=1,int pa=1,int t=1,int cnt=0){
int cnt=0; return gettop(now,pa,t,cnt);
}
給定一棵樹
支援兩種操作
修改一條路徑上的點權
及查詢兩點間距離
\((N<10^5)\)
void modify(int a,int b,int k){
while(top[a]!=top[b]){
if(d[top[a]]<d[top[b]]) swap(a,b);
add(ind[top[a]],ind[a],k);
a=p[top[a]];
}
if(d[a]<d[b]) swap(a,b);
add(ind[b],ind[a],k);
}
int query(int a,int b){
int tot=0;
while(top[a]!=top[b]){
if(d[top[a]]<d[top[b]]) swap(a,b);
tot+=get(ind[top[a]],ind[a]);
a=p[top[a]];
}
if(d[a]<d[b]) swap(a,b);
tot+=get(ind[b],ind[a]);
return tot;
}
給定一個簡單帶權圖
求出刪掉一個邊的最小生成樹最大值
給定一棵以 \(1\) 為根,包含 \(n\) 個節點的樹,每個節點有一個顏色 \(c_i\),求樹中每個子樹出現最多次的顏色編號的和
\((n \leq 10^5)\)
路徑壓縮 | ||
啟發式合併 | ||
\(O( \alpha (n) )\)
\(O( \log n )\)
\(O( \log_{2+f/n} n ) \)
\(O( n )\)
補充額外冷知識(但講師不會證明QAQ
給定一棵以 \(1\) 為根,包含 \(n\) 個節點的樹以及預算上限 \(M\),每個節點(忍者)分別有出動費用 \(C_i\) 和領導力值 \(L_i\),假設以節點 \(i\) 為領導者,其所能造成的滿意度是
\(L_i \times\) (在預算內能在其子樹內出動的最多忍者數量)
請求出在預算內能夠達到的最大滿意度
\((n \leq 10^5, M \leq 10^9)\)
給定一座包含 \(n\) 個節點的森林,接著是 \(m\) 筆詢問,每次詢問一個點與多少個點擁有共同的 \(K\) 倍祖先
\((n, m \leq 10^5)\)
給定一棵以 \(1\) 為根,包含 \(n\) 個節點的樹
設 \(d(u, x)\) 為 \(u\) 子樹中到 \(u\) 距離為 \(x\) 的節點數。 對於每個點,求一個最小的 \(k\),使得 \(d(u, k)\) 最大。
\((n \leq 10^6)\)
給定一棵以 \(1\) 為根,包含 \(n\) 個節點的樹,一開始每個節點皆為藍色,接下來有 \(q\) 筆操作,操作分為兩種,一種是將一個點塗成紅色,另一種則是詢問一個點與距離他最近的紅點之距離
\((n, q \leq 10^5)\)
給定一棵包含 \(n\) 個節點的樹,要求把上面的所有節點用 A 到 Z 標記,使得對於任意兩個標記相同的節點,它們之間的最短路上至少有一個標記(字典序)更小的節點。
\((n \leq 10^5)\)
給定一棵包含 \(n\) 個節點的樹,要求把上面的所有節點用 A 到 Z 標記,使得對於任意兩個標記相同的節點,它們之間的最短路上至少有一個標記(字典序)更小的節點。
\((n \leq 10^5)\)
給定一棵包含 \(n\) 條邊(邊有邊權)的聯通圖,求刪掉一條邊所形成的樹中,所能夠產生的最小直徑。
\((n \leq 2 \cdot 10^5)\)
給定一棵樹
每個節點一個顏色
對於 \(q\) 筆詢問 \(a_i,b_i\)
回答節點 \(a_i,b_i\) 之間路徑上顏色的眾數數量
\((n,q<5\times10^4)\)
Euler Tour Order:
\(a=lca(b)\)
假設 \(start(a)<start(b)\)
\(query(a,b)=[start(a),start(b)]\)
\(a\ne lca(b)\)
\(query(a,b)=[end(a),start(b)]+start(lca(a,b))\)