Submission #409448

#TimeUsernameProblemLanguageResultExecution timeMemory
409448ivycubeRegions (IOI09_regions)C++14
0 / 100
936 ms32396 KiB
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>

using namespace std;
using PII = pair<int, int>;

const int N = 200005, R = 25005, UP = 450 /*threshold*/;

int n, m, k, a[N], ord, st[N], ed[N];
vector<int> adj[N], region[R], large_region;
vector<vector<int>> large_r1, large_r2;
map<int, int> region_idx;

void dfs(int u) {
    st[u] = ++ord;
    for (auto v : adj[u]) dfs(v);
    ed[u] = ord;
}

inline bool cmp(const int &a, const int &b) {
    return st[a] < st[b];
}

void dfs1(int u, int r1, int cnt = 0) {
    cnt += (a[u] == r1);
    large_r1[region_idx[r1]][a[u]] += cnt; // count all employee in subtree for r1
    for (auto v : adj[u]) dfs1(v, r1, cnt);
}

int dfs2(int u, int r2) {
    int cnt = (a[u] == r2);     // count all ancestors for r2
    for (auto v : adj[u]) cnt += dfs2(v, r2);
    large_r2[region_idx[r2]][a[u]] += cnt;
    return cnt;
}

void calc_large() {
    large_r1.resize((int)large_region.size() + 1, vector<int>(k + 1, 0));
    large_r2.resize((int)large_region.size() + 1, vector<int>(k + 1, 0));
    int idx = 0;
    for (auto r : large_region) {
        region_idx[r] = ++idx;
        dfs1(1, r);
        dfs2(1, r);
    }
}

inline bool ancestor_of(const int &a, const int &b) {
    return st[a] <= st[b] && ed[b] <= ed[a];
}

int calc(int r1, int r2) {
    vector<int> blocks(region[r1].begin(), region[r1].end());
    blocks.insert(blocks.end(), region[r2].begin(), region[r2].end());
    sort(blocks.begin(), blocks.end(), cmp);
    
    int res = 0;
    vector<int> stk;
    for (auto u : blocks) {
        while(!stk.empty() && !ancestor_of(stk.back(), u)) stk.pop_back();
        if (a[u] == r1) stk.push_back(u);
        else res += (int) stk.size();
    }
    return res;
}

int main() {
    scanf("%d%d%d", &n, &k, &m);
    scanf("%d", &a[1]);
    region[a[1]].push_back(1);
    
    int j;
    for (int i = 2; i <= n; i++) {
        scanf("%d%d", &j, &a[i]);
        adj[j].push_back(i);
        region[a[i]].push_back(i);
    }
    
    dfs(1);
    for (int i = 1; i <= k; i++) {
        sort(region[i].begin(), region[i].end(), cmp);
        if (region[i].size() > UP) large_region.push_back(i);
    }
    
    calc_large();
    
    int r1, r2;
    for (int i = 0; i < m; i++) {
        scanf("%d%d", &r1, &r2);
        if (region[r1].size() > UP)
            printf("%d\n", large_r1[region_idx[r1]][r2]);
        else if (region[r2].size() > UP)
            printf("%d\n", large_r2[region_idx[r2]][r1]);
        else
            printf("%d\n", calc(r1, r2));
    }
    
    return 0;
}

Compilation message (stderr)

regions.cpp: In function 'int main()':
regions.cpp:71:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   71 |     scanf("%d%d%d", &n, &k, &m);
      |     ~~~~~^~~~~~~~~~~~~~~~~~~~~~
regions.cpp:72:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   72 |     scanf("%d", &a[1]);
      |     ~~~~~^~~~~~~~~~~~~
regions.cpp:77:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   77 |         scanf("%d%d", &j, &a[i]);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~
regions.cpp:92:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   92 |         scanf("%d%d", &r1, &r2);
      |         ~~~~~^~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...