發表文章

目前顯示的是有「啟發式合併」標籤的文章

[Codeforces] 208E. Blood Cousins

題目連結: http://codeforces.com/problemset/problem/208/E 稍微轉化一下問題就可以得到問節點$i$的子節點們深度為$d$的有那些,轉法也很簡單,對於一組詢問$(v, p)$就直接變成,對於$v$的$p$倍祖先問在$dep[v]$的數字有哪些(問一個人的$p$倍祖先可以直接用個倍增法做到)。轉化成這樣後就可以直接開個map維護每個深度為$k$時有幾個,然後要合併兩子樹就啟發式合併就好了。 #include <bits/stdc++.h> using namespace std; const int N = 100000 + 5; typedef pair<int,int> PII; #define PB push_back #define FF first #define SS second class K_anc{ private: vector<int> G[N]; int anc[N][20]; void dfs(int w, int f){ anc[w][0]=f; for(auto i: G[w]) if(i!=f) dfs(i, w); } public: inline void AddEdge(int u, int v){ G[u].PB(v); G[v].PB(u); } void solve(int r, int maxn){ dfs(r, r); for(int j=1;j<20;j++) for(int i=0;i<maxn;i++){ anc[i][j] = anc[anc[i][j-1]][j-1]; ...

[Codeforces] 570D. Tree Requests

題目連結: http://codeforces.com/contest/570/problem/D 把詢問依照節點存好,接下來我們就可以對樹DFS,同時記錄一下他的深度與每個字母出現的次數,然後要把兩棵子樹的資訊合併起來時就用啟發式合併,而完成一棵子樹後就可以把每個詢問的答案填上去,而且我們只在意奇偶性,所以甚至還可以用位元運算壓掉一些常數,大概就這樣吧。 #include <bits/stdc++.h> using namespace std; #define PB push_back typedef pair<int,int> PII; #define FF first #define SS second const int N = 500000 + 5; vector<int> G[N]; char wh[N]; vector<PII> que[N]; int ans[N], dep[N]; void dfs(int, map<int,int>&); int main(){ int n, q; scanf("%d%d",&n,&q); dep[1]=1; for(int i=2;i<=n;i++){ int x; scanf("%d", &x); G[x].PB(i); dep[i]=dep[x]+1; } scanf("%s", wh); for(int i=0;i<q;i++){ int v, d; scanf("%d%d", &v, &d); if(d < dep[v]) continue; que[v].PB({d, i}); } map<int,int> mp...

[Codeforces] 600E. Lomsat gelral

題目連結: http://codeforces.com/problemset/problem/600/E 詢問子樹區間眾數和,一開始我只想到可以樹壓扁莫隊。後來被雷了之後才知道可以啟發式合併,讓子樹回傳一個map之類的東西記錄每個數字有幾個,而要把子樹們合起來的方式則採用啟發是合併,這樣可以保證每個數字最多被合併$logN$次,要算答案也很簡單,就簡單的看一下現在最大的數字個數有幾個跟維護一下和就好。 #include <bits/stdc++.h> using namespace std; #define PB push_back typedef long long lld; typedef pair<lld,int> PLI; #define FF first #define SS second const int N = 100000 + 5; int col[N]; lld ans[N]; vector<int> G[N]; PLI dfs(int,int,unordered_map<int,int>&); int main(){ ios_base::sync_with_stdio(0);cin.tie(0); int n; cin>>n; for(int i=1;i<=n;i++) cin>>col[i]; for(int i=0;i<n-1;i++){ int u, v; cin>>u>>v; G[u].PB(v); G[v].PB(u); } unordered_map<int,int> mp; dfs(1, 1, mp); for(int i=1;i<=n;i++) cout<<ans[i]<<" \n"[i==n]; return 0;...