Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include<bits/stdc++.h>
- using namespace std;
- void Read(int &val) {
- val = 0; char c;
- do { c = getchar(); } while (!isdigit(c));
- while (isdigit(c)) { val = val * 10 + c - '0'; c = getchar(); }
- }
- void Write(int val) {
- if (val < 10) putchar('0' + val);
- else Write(val/10), putchar('0' + val%10);
- }
- const int N = 2e5 + 4, SQ = 504, COLOR = 25004;
- int n, numColor, Q, color[N];
- vector<int> adj[N];
- int numVer[N], Map[N];
- vector<int> lsVer[COLOR], Small, Big;
- int Big_dad[SQ][COLOR], Big_son[SQ][COLOR];
- int Count[N], cnt;
- void DFS(int par, int u, int col) {
- Count[u] = (color[u] == col);
- cnt += (color[u] == col);
- for (int v : adj[u]) if (v != par) {
- DFS(u, v, col);
- Count[u] += Count[v];
- }
- Big_son[Map[col]][color[u]] += Count[u];
- Big_dad[Map[col]][color[u]] += cnt;
- cnt -= (color[u] == col);
- }
- void prepare_BigCase() {
- for (int col : Big) {
- for (int i = 1; i <= numColor; ++i) Count[i] = 0; cnt = 0;
- DFS(0, 1, col);
- }
- }
- int numET, Begin[N], End[N], Match[N];
- void Build_ETT(int par, int u) {
- Begin[u] = ++numET; Match[numET] = u;
- for (int v : adj[u]) if (v != par) Build_ETT(u, v);
- End[u] = numET;
- }
- vector<int> L[COLOR], R[COLOR];
- void prepare_SmallCase() {
- Build_ETT(0, 1);
- for (int col : Small) {
- sort(lsVer[col].begin(), lsVer[col].end(), [] (int &a, int &b) {
- return Begin[a] < Begin[b];
- });
- for (int ver : lsVer[col]) L[col].push_back(Begin[ver]), R[col].push_back(End[ver]);
- R[col].resize(unique(R[col].begin(), R[col].end()) - R[col].begin());
- }
- }
- vector<int> V, tmp;
- int partial[N], pos[N];
- int process_Small(int u, int v) {
- /// use Merge_sort
- tmp.clear(); V.clear();
- tmp.resize(L[u].size()+R[u].size());
- V.resize(L[u].size() + L[v].size() + R[u].size());
- merge(L[u].begin(), L[u].end(), R[u].begin(), R[u].end(), tmp.begin());
- merge(L[v].begin(), L[v].end(), tmp.begin(), tmp.end(), V.begin());
- V.resize(unique(V.begin(), V.end())- V.begin());
- for (int i = 0; i < (int) V.size(); ++i) {
- pos[V[i]] = i;
- partial[i] = (i == 0) ? 0 : partial[i-1];
- if (color[ Match[V[i]] ] == v) partial[i]++;
- }
- int res = 0;
- for (int ver : lsVer[u]) {
- int l = pos[Begin[ver]], r = pos[End[ver]];
- res += (l == 0) ? partial[r] : partial[r] - partial[l-1];
- }
- return res;
- }
- void Answer_Query() {
- int u, v, res;
- while (Q--) {
- Read(u); Read(v); res = 0;
- if (numVer[u] > sqrt(n)) res = Big_dad[Map[u]][v];
- else if (numVer[v] > sqrt(n)) res = Big_son[Map[v]][u];
- else res = process_Small(u, v);
- Write(res); putchar('\n');
- }
- }
- void sol() {
- for (int u = 1; u <= n; ++u) {
- numVer[color[u]]++;
- lsVer[color[u]].push_back(u);
- }
- for (int i = 1; i <= numColor; ++i) {
- if (numVer[i] > sqrt(n)) Big.push_back(i), Map[i] = Big.size()-1;
- else Small.push_back(i), Map[i] = Small.size()-1;
- }
- prepare_BigCase();
- prepare_SmallCase();
- Answer_Query();
- }
- int main() {
- if (fopen("input.txt", "r")) {
- freopen("input.txt", "r", stdin);
- }
- else {
- freopen("coltree.in", "r", stdin);
- freopen("coltree.out", "w", stdout);
- }
- Read(n); Read(numColor); Read(Q);
- Read(color[1]);
- int v;
- for (int u = 2; u <= n; ++u) {
- Read(v); Read(color[u]);
- adj[u].push_back(v); adj[v].push_back(u);
- }
- sol();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement