題意
Sol
很神仙的題
我們考慮詢問(a, b)(a是b的祖先),直接對b根號分治
如果b的出現次數(< sqrt{n}),我們可以直接對每個b記錄下與它有關的詢問,這樣每個詢問至多掃(sqrt{n})個點即可知道答案,那麼dfs的時候暴力統計答案即可,複雜度(qsqrt{n})
如果b的出現次數(> sqrt{n}),顯然這樣的b最多隻有(sqrt{n})個,也就是說在詢問中最多會有(sqrt{n})個這樣的b,那麼我們可以對每個a,暴力統計,複雜度(nsqrt{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
", ans[i]);
return 0;
}