제출 #525645

#제출 시각아이디문제언어결과실행 시간메모리
525645Aldas25Regions (IOI09_regions)C++14
100 / 100
3807 ms34348 KiB
#include <bits/stdc++.h>

using namespace std;

#define FAST_IO ios_base::sync_with_stdio(0); cin.tie(0)
#define FOR(i, a, b) for(int i = (a); i <= (b); i++)
#define REP(n) FOR(O, 1, (n))
#define pb push_back
#define f first
#define s second
typedef long double ld;
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<pii> vii;
//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int MAXN = 250100, MAXK = 20;
const ll MOD = 1e9+7;

const ll C = 500;
const ll c = 500;

int n, r, q;
int h[MAXN];
int regSz[MAXN];
bool bgReg[MAXN];
vi adj[MAXN];

int regToId[MAXN];
int idToReg[MAXN];

int tin[MAXN], tout[MAXN];
int crT = 0;

void dfs (int v, int p = -1) {
    tin[v] = ++crT;

    for (int u : adj[v]) {
        dfs (u, v);
    }

    tout[v] = crT;
}

bool isAnc (int a, int b) {
    return (tin[a] <= tin[b] && tout[b] <= tout[a]);
}

vii nodes;
vii inReg[MAXN];
ll pref[MAXN];
ll ans[C][25100];

int getUpperBound (int r, int x) {
    int sz = (int)inReg[r].size();
    if (sz == 0) return sz;
    if (inReg[r][sz-1].f <= x) return sz;

    int le = 0, ri = sz-1;
    while (le < ri) {
        int m = (le+ri)/2;
        if (inReg[r][m].f > x) ri = m;
        else le = m+1;
    }

    return le;
}

int main()
{
    FAST_IO;

    cin >> n >> r >> q;
    cin >> h[1];
    FOR(i, 2, n) {
        int pr; cin >> pr;
        adj[pr].pb(i);
        cin >> h[i];

    }

    FOR(i, 1, n) regSz[h[i]]++;
    int lstId = 0;
    FOR(i, 1, r) {
        bgReg[i] = (regSz[i] > c);

        if (bgReg[i]) {
            regToId[i] = ++lstId;
            idToReg[lstId] = i;
        }

       // cout << " i = " << i << " regSz = " << regSz[i] << " bg = " << bgReg[i] << endl;
       // if (bgReg[i]) cout << "     regToId[i]=" << regToId[i] << endl;
    }

    dfs(1);

    FOR(i, 1, n) {
        nodes.pb({tin[i], i});
        inReg[h[i]].pb({tin[i], i});
    }

    sort(nodes.begin(), nodes.end());
    FOR(i, 1, r) sort(inReg[i].begin(), inReg[i].end());

    FOR(i, 0, C-1) {
        if (idToReg[i] == 0) continue;
        int r = idToReg[i];

        FOR(j, 0, n) pref[j] = 0;
        for (auto p : inReg[r]) {
            int v = p.s;
            pref[tin[v]]++;
            pref[tout[v]+1]--;
        }
        FOR(j, 1, n) pref[j] += pref[j-1];

        FOR(j, 1, n) {
            int v = nodes[j-1].s;
            ans[i][h[v]] += pref[j];
        }

    }

    REP(q) {
        int r1, r2;
        cin >> r1 >> r2;

        if (bgReg[r1]) {
            cout << ans[regToId[r1]][r2] << endl;
        } else {
            ll ats = 0;
            for (auto p : inReg[r1]) {
                int v = p.s;

                int ri = getUpperBound (r2, tout[v]);
                int le = getUpperBound (r2, tin[v]);

                ats += max(0, ri-le);
            }

            cout << ats << endl;
        }
    }

    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...