Submission #926845

# Submission time Handle Problem Language Result Execution time Memory
926845 2024-02-13T23:05:10 Z bobbilyking Werewolf (IOI18_werewolf) C++17
0 / 100
2115 ms 126468 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; // this is sus 
            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;

        // This case happens when we relabel to the root for multiple nodes. In this case, we've already compressed the relabeling, so we're good.
        // (Here is an example of a data structure where it's trivial to update things from bototm up, but hard to know what to dfs into top-down).
        if (!nodesInSubtree[node].count(relabelFrom)) return; 


        // this is correct since we're just locally compressing the sequence, we're not doing anything fancy like passing up the time. 
        // in the brute force version, we'd maintain the entire sequence of relabeled nodes per thing.
        // but obviously, we can compress all of those, and then only the maximum time (e.g. earliest suffix) matters.
        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:113:5: note: in expansion of macro 'F'
  113 |     F(i, 0, X.size()) {
      |     ^
# Verdict Execution time Memory Grader output
1 Incorrect 3 ms 15964 KB Output isn't correct
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 3 ms 15964 KB Output isn't correct
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 2115 ms 126468 KB Output isn't correct
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 3 ms 15964 KB Output isn't correct
2 Halted 0 ms 0 KB -