題解 BZOJ BZOJ4668 冷戰

2022-07-25 16:48:24 字數 1539 閱讀 5804

題外話:

你們知道想了半天思路提供給同學然後證明了半天時間複雜度然後考試結束的痛苦嗎……

看到連通性,我們會本能地想起並查集(想起lct的說明您太強了orz)

題目要求輸出的是\((u,v)\)這一點對最早在什麼時候聯通

考慮連邊操作

顯然,如果\((u,v)\)已經聯通,那麼連線它們兩個是沒有意義的

如果\((u,v)\)不連通,則必須連線它們兩個

經過一番思考,我們思考出來以下思路:

若連線\((u,v)\),則將\(u\)並查集合並到\(v\)並查集上

連出來的邊設乙個邊權\(val\),val為當前為第幾個鐵路

好像就沒有了?

對於詢問,我們直接往上一層層跳,跳出lca,然後統計答案

在實際實現的時候,每個點會記錄乙個\(v[i]\),表示i到fa[i]這條路徑上的權值

同時,為了方便,我(在參考lzh的**後)選取了另外一種更暴力的找lca的方法

注意:不能路徑壓縮,為了保證時間複雜度我們使用按高度合併(學名不知道……)

期望?均攤?反正層數\(o(logn)\)

code:

#include #include #include #include using namespace std;

const int n=500010;

const int inf=2e9;

inline void read(int &x)

ch=getchar();

}while(ch>='0'&&ch<='9')

x*=f;}/*

f[i]:常規並查集記錄fa

v[i]:從i到f[i]這條邊的權值

h[i]:i所在子樹的高度

dep[i]:i所在子樹中i的深度

*/int f[n],v[n],h[n];

int dep[n];

int n,m;

inline int find(int x)

return x;

}inline int check(int x,int y)

inline void merge(int x,int y,int val) else

}//vis[i]:i在搜尋過程中是否被找過

int vis[n];

inline int find(int x,int val)

vis[x]=val;

return x;

}inline int query(int x,int y)

if (!vis[lca])

find(x,0);

int ans=0;

while(x!=lca)

while(y!=lca)

return ans;

}int main()

int last_ans=0,cnt=0;

for(int i=1;i<=m;i++)

merge(x,y,cnt);

} else

}return 0;

}

出題 題解4

由於3比較水略過 這個你只要對所有vi 按p取模,然後排個序,再列舉每個點,按照p vi在陣列上二分即可。有個坑就是二分到的可能是自己,造資料的時候特意卡了一下,不跳的就只有40分。這個你只要考慮每條邊在答案裡的貢獻即可,列舉 v 子樹to 裡黑點的個數 w 然後這條邊的貢獻就是 k w w va ...

《題單》 4題解

給你乙個正整數n,判斷n能否被3 5 8 11中的乙個或多個數整除。n 1e50 由於正整數過大,因此n用字串進行儲存,只要判斷 n 3,5,8,11 是否等於0,也就是課上講的大數取模,利用大數取模來進行判斷即可。乙個數字abc k 可以拆解為 a 10 b 10 c k,根據乘法取模的性質,將取...

Wannafly模擬賽4 題解

a fst是一名可憐的小朋友,他很強,但是經常fst,所以rating一直低迷。但是重點在於,他非常適合acm!並在最近的區域賽中獲得了不錯的成績。拿到獎金後fst決定買一台新筆記本,但是fst發現,在 能承受的範圍內,筆記本的記憶體和速度是不可兼得的。可是,有一些筆記本是被另外一些 完虐 的,也就...