제출 #1307252

#제출 시각아이디문제언어결과실행 시간메모리
1307252buzdiRegions (IOI09_regions)C++17
90 / 100
8023 ms35480 KiB
#include <bits/stdc++.h>
#define ll long long

using namespace std;

const int NMAX = 2e5;
const int RMAX = 25000;
const int BLOCK = 500;

int n, r, q, t;
int reg[NMAX + 1];
int freq[RMAX + 1];
int in[NMAX + 1], out[NMAX + 1];
int sp[NMAX + 1];
vector<int> g[NMAX + 1], in_reg[RMAX + 1], out_reg[RMAX + 1], nodes_reg[RMAX + 1];

void DFS(int node, int dad = 0) {
    in[node] = ++t;
    in_reg[reg[node]].push_back(in[node]);
    for(int next_node : g[node]) {
        if(next_node != dad) {
            DFS(next_node, node);
        }
    }
    out[node] = t;
    out_reg[reg[node]].push_back(out[node]);
}

int lower_bound_in(vector<int>& a, vector<int>& b) {
    int sz_a = a.size(), sz_b = b.size(), i = 0, j = 0, answer = 0;
    while(i < sz_a && j < sz_b) {
        if(a[i] <= b[j]) {
            answer += sz_b - j;
            i++;
        }
        else {
            j++;
        }
    }
    return answer;
}

int upper_bound_out(vector<int>& a, vector<int>& b) {
    int sz_a = a.size(), sz_b = b.size(), i = 0, j = 0, answer = 0;
    while(i < sz_a && j < sz_b) {
        if(a[i] < b[j]) {
            answer += sz_b - j;
            i++;
        }
        else {
            j++;
        }
    }
    return answer;
}

int query_both_small(int r1, int r2) {
    return lower_bound_in(in_reg[r1], in_reg[r2]) - upper_bound_out(out_reg[r1], in_reg[r2]);
}

int query_small(int r1, int r2) {
    int answer = 0;
    for(int node : nodes_reg[r1]) {
        auto itr = upper_bound(in_reg[r2].begin(), in_reg[r2].end(), out[node]);
        auto itl = lower_bound(in_reg[r2].begin(), in_reg[r2].end(), in[node]);
        answer += itr - itl;
    }
    return answer;
}

int query_big(int r1, int r2) {
    /// Activate r2
    /// Query r1

    fill(sp + 1, sp + n + 1, 0);
    for(int node : nodes_reg[r2]) {
        sp[in[node]]++;
    }
    for(int i = 1; i <= n; i++) {
        sp[i] += sp[i - 1];
    }

    int answer = 0;
    for(int node : nodes_reg[r1]) {
        answer += sp[out[node]] - sp[in[node] - 1];
    }
    return answer;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    cin >> n >> r >> q;
    cin >> reg[1];
    for(int i = 2; i <= n; i++) {
        int x;
        cin >> x >> reg[i];
        g[x].push_back(i);
        g[i].push_back(x);
    }

    for(int i = 1; i <= n; i++) {
        freq[reg[i]]++;
        nodes_reg[reg[i]].push_back(i);
    }
    DFS(1);

    while(q--) {
        int r1, r2;
        cin >> r1 >> r2;
        if(freq[r1] <= BLOCK && freq[r2] <= BLOCK) {
            cout << query_both_small(r1, r2) << endl;
        }
        else if(freq[r1] <= BLOCK) {
            cout << query_small(r1, r2) << endl;
        }
        else {
            cout << query_big(r1, r2) << endl;
        }
    }
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...