Submission #926842

# Submission time Handle Problem Language Result Execution time Memory
926842 2024-02-13T22:30:18 Z bobbilyking Werewolf (IOI18_werewolf) C++17
0 / 100
483 ms 260840 KB
#include "werewolf.h"
#include <bits/stdc++.h>
using namespace std;

using ll = int;
#define F(i, l, r) for (ll i = (l); i < (r); ++i)
#define A(a) (a).begin(), (a).end()
using pl = pair<ll, ll>;

using vl = vector<ll>;
#define K first 
#define V second
#define NN 200010
ll parent[NN];
vl dsuSet[NN];
ll find(ll i) {
    while ( i - parent[i]) i = parent[i];
    return i;
}

optional<pair<pl, vl>> merge(ll i, ll j) {
    i = find(i), j = find(j);
    if (i-j) {
        if (dsuSet[i].size() < dsuSet[j].size()) swap(i, j);
        parent[j] = i;
        dsuSet[i].insert(dsuSet[i].end(), A(dsuSet[j]));
        return {pair(pair(i, j), dsuSet[j])};
    }
    return {};
}

// another alternate form of the kruskal reconstruction tree
// We're trying to maintain, "does node E exists in my KRT subtree?"
// Hard to maintain with normal KRT.
// Instead, let's store in the event-KRT 

namespace krt {
    ll parent[NN];
    map<ll, ll> nodesInSubtree[NN]; 

    ll pw[NN];
    
    ll find(ll i) {
        while (i - parent[i]) i = parent[i];
        return i;
    }

    void merge(ll i, ll j, ll w) {
        i = find(i), j = find(j);
        if (i-j) {
            if (nodesInSubtree[i].size() < nodesInSubtree[j].size()) {
                swap(i, j);
            }
            for (auto &[x, _]: nodesInSubtree[j]) nodesInSubtree[i][x] = w;

            pw[j] = w;
            parent[j] = i;
        }
    }

    void init(ll n) {
        F(i, 0, n) {
            nodesInSubtree[i][i] = n-1;
            parent[i] = i;
        }
    }

    void change(ll node, ll relabelFrom, ll relabelTo) {
        // cout << "CHANGE " << endl;
        // cout << "START NODE: " << node << " " << relabelFrom << " -> " << relabelTo << endl;
        // for (auto [k, v]: nodesInSubtree[node]) cout << k << " " << v << " | "; cout << endl;

        assert(nodesInSubtree[node].count(relabelFrom));
        ll v = nodesInSubtree[node][relabelFrom];
        nodesInSubtree[node].erase(relabelFrom);
        
        nodesInSubtree[node][relabelTo] = max(nodesInSubtree[node][relabelTo], v);

        if (node != parent[node]) change(parent[node], relabelFrom, relabelTo);
    }

    // this is a bit... sus.
    bool query(ll node, ll searchLabel, ll w) {
        auto it = nodesInSubtree[node].find(searchLabel); 
        if (it != nodesInSubtree[node].end() and it->V >= w)  return true;

        if (node != parent[node] and pw[node] >= w) return query(parent[node], searchLabel, w);
        return false;
    }
}


std::vector<int> check_validity(int N, std::vector<int> X, std::vector<int> Y,
                                std::vector<int> S, std::vector<int> E,
                                std::vector<int> L, std::vector<int> R) {

    ll Q = R.size();
    vector<vector<pl>> queries(N);
    std::vector<int> ans(Q);

    F(i, 0, Q) {
        queries[R[i]].emplace_back(L[i], i);
    }

    vector<vector<pl>> edges(N), edgesPre(N);
    F(i, 0, X.size()) {
        edges[max(X[i], Y[i])].emplace_back(X[i], Y[i]);
        edgesPre[min(X[i], Y[i])].emplace_back(X[i], Y[i]);
    }

    // E means u can go from [L, N-1] in the suffix dSU
    krt::init(N);
    for (ll i = N-1; i >= 0; --i) for (auto [x, y]: edgesPre[i]) {
        krt::merge(x, y, i);
    }

    // S means u can go from [0, R] in the prefix DSU

    F(i, 0, N) {
        parent[i] = i;
        dsuSet[i] = {i};
    }

    F(right, 0, N) {
        for (auto &[x, y]: edges[right]) {
            auto result = merge(x, y);
            if (result.has_value()) {
                auto [relabel, nodes] = *result;
                for (auto x: nodes) {
                    krt::change(x, relabel.V, relabel.K);
                }
            }
        }
        for (auto &[left, qidx]: queries[right]) {
            ll queryLabel = find(S[qidx]);
            ans[qidx] = krt::query(E[qidx], queryLabel, left);
        }
    }

    return ans;
}

Compilation message

werewolf.cpp: In function 'std::vector<int> check_validity(int, std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>)':
werewolf.cpp:6:39: warning: comparison of integer expressions of different signedness: 'll' {aka 'int'} and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
    6 | #define F(i, l, r) for (ll i = (l); i < (r); ++i)
      |                                       ^
werewolf.cpp:106:5: note: in expansion of macro 'F'
  106 |     F(i, 0, X.size()) {
      |     ^
# Verdict Execution time Memory Grader output
1 Runtime error 15 ms 32244 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Runtime error 15 ms 32244 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Runtime error 483 ms 260840 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Runtime error 15 ms 32244 KB Execution killed with signal 6
2 Halted 0 ms 0 KB -