BZOJ3351: [ioi2009]Regions(根號分治)
阿新 • • 發佈:2019-02-01
會有 read push getc mes base sin \n const
題意
題目鏈接
Sol
很神仙的題
我們考慮詢問(a, b)(a是b的祖先),直接對b根號分治
如果b的出現次數\(< \sqrt{n}\),我們可以直接對每個b記錄下與它有關的詢問,這樣每個詢問至多掃\(\sqrt{n}\)個點即可知道答案,那麽dfs的時候暴力統計答案即可,復雜度\(q\sqrt{n}\)
如果b的出現次數\(> \sqrt{n}\),顯然這樣的b最多只有\(\sqrt{n}\)個,也就是說在詢問中最多會有\(\sqrt{n}\)個這樣的b,那麽我們可以對每個a,暴力統計,復雜度\(n\sqrt{n}\)
然後用天天愛跑步那題的差分技巧搞一下就行了
代碼十分好寫~
#include<bits/stdc++.h> #define Pair pair<int, int> #define MP(x, y) make_pair(x, y) #define fi first #define se second //#define int long long #define LL long long #define Fin(x) {freopen(#x".in","r",stdin);} #define Fout(x) {freopen(#x".out","w",stdout);} using namespace std; const int MAXN = 1e6 + 10; inline int read() { char c = getchar(); int x = 0, f = 1; while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * f; } int N, R, Q, base; vector<int> v[MAXN]; vector<Pair> a1[MAXN], a2[MAXN]; int r[MAXN], fa[MAXN], ti[MAXN], ha[MAXN], ans[MAXN]; void dfs1(int x) { for(auto &a : a1[r[x]]) ans[a.se] += ha[a.fi]; ha[r[x]]++; for(auto &to : v[x]) dfs1(to); ha[r[x]]--; } void dfs2(int x) { for(auto &b: a2[r[x]]) ans[b.se] -= ha[b.fi]; for(auto &to: v[x]) dfs2(to); for(auto &b: a2[r[x]]) ans[b.se] += ha[b.fi]; ha[r[x]]++; } signed main() { // Fin(9); Fout(b); N = read(); R = read(); Q = read(); base = sqrt(N); r[1] = read(); ti[r[1]]++; for(int i = 2; i <= N; i++) { int f = read(); r[i] = read(); v[f].push_back(i); ti[r[i]]++; } for(int i = 1; i <= Q; i++) { int a = read(), b = read(); if(ti[b] < base) { a1[b].push_back({a, i}); } else { a2[a].push_back({b, i}); } } dfs1(1); memset(ha, 0, sizeof(ha)); dfs2(1); for(int i = 1; i <= Q; i++) printf("%d\n", ans[i]); return 0; }
BZOJ3351: [ioi2009]Regions(根號分治)