HDU4858 專案管理(圖分塊)
阿新 • • 發佈:2021-10-28
目錄
Description
有 \(n\) 個節點,有 \(m\) 條邊,有 \(Q\) 次操作
\(0\ u\ v\): 節點 \(u\) 的權值增加 \(v\)
\(1\ u\): 輸出與 \(u\) 相連的節點所有節點之和
State
\(1<=n<=10^5\)
\(1<=m<=n+10\)
\(1<=v<=100\)
Input
1
3 2
1 2
1 3
6
0 1 15
0 3 4
1 1
1 3
0 2 33
1 2
Output
4
15
15
Solution
圖中有兩種節點,一種是節點度小於等於 \(\sqrt{m}\) 的,另一種是大於 \(\sqrt{m}\) 的;
而對於操作 $ 0$ 時間複雜度為 \(O(1)\),操作 \(1\) 最壞為 \(O(m)\)
這顯然是不可取的;但是對於第一種節點的查詢操作為 \(O(\sqrt{m})\),如果將第二種節點查詢複雜度降下來的話,複雜度應該是可行的
這時只關心第二種節點,與第二種節點相連的仍然是這兩種節點。
對於一個重結點 \(x\) ,與其相連的節點更新時如果想要波及到 \(x\) 的話,這兩種點都要連線 \(x\),也就是說:
輕節點只要連線重節點,重節點只要連線重節點,在更新時就可以滿足時間上的要求了
在這裡輕節點的度顯然小於等於 \(\sqrt{m}\),而重節點最多有 \(\sqrt{m}\) 個,所以重節點的度也為 \(\sqrt{m}\)
Code
const int N = 1e5 + 5; int n, m, k, _; vector<int> G[N], G2[N]; int block; int sum[N], ans[N]; void clear() { for(int i = 1; i <= n; i ++){ G[i].clear(); G2[i].clear(); sum[i] = ans[i] = 0; } } signed main() { // IOS; rush(){ sdd(n, m); int x, y; rep(i, 1, m){ sdd(x, y); G[x].pb(y); G[y].pb(x); } block = sqrt(m); for(int i = 1; i <= n; i ++){ for(int j = 0; j < G[i].size(); j ++){ x = G[i][j]; if(G[x].size() > block) G2[i].pb(x); } } int Q = read(); for(int k = 1; k <= Q; k ++){ int opt, u, v; sdd(opt, u); if(opt == 0){ sd(v); ans[u] += v; for(auto it : G2[u]){ sum[it] += v; } } else{ int res = 0; if(G[u].size() <= block){ for(auto it : G[u]){ res += ans[it]; } } else{ res = sum[u]; } pd(res); } } clear(); } // PAUSE; return 0; }