Submission #1335016

#TimeUsernameProblemLanguageResultExecution timeMemory
1335016mattartaSplit the Attractions (IOI19_split)C++20
18 / 100
68 ms27816 KiB
#include "split.h"
#include <bits/stdc++.h>

#ifdef DEBUG
    #define debug(...) println(clog, __VA_ARGS__)
#else
    #define debug(...)
#endif

#define forall(i, s, e) for(int i=(s); i<(e); i++)

#define sz(x) (int)(x).size()

using namespace std;

using ll = long long;

using vi = vector<int>;
using vl = vector<ll>;
using vb = vector<bool>;

using aii = array<int, 2>;
using all = array<ll, 2>;

const int inf = 1e8;

int N;
vector<vi> G, T;

vi S;

vi ans;
vi dv;

vi tin, low;

void fill_subtree(int v, int x, vi &out) {
    if(out[v] != -1) return;
    
    out[v] = x;

    for(int c:T[v])
        fill_subtree(c, x, out);
}

bool divide_ty1(int v, int a) {
    debug("DV1 {}", v);

    fill_subtree(v, 0, dv);

    forall(i, 0, N)
        if(dv[i] == -1) dv[i] = 1;
    
    return 1;
}

bool divide_ty2(int v, int a) {
    debug("DV2 {}", v);

    int s = 1;

    dv[v] = 0;

    for(int c:T[v]) {
        if(low[c] >= tin[v]) {
            s += S[c];
            debug("fill {} (1)", c);
            fill_subtree(c, 0, dv);
        }
    }

    if(s > N-a)
        return 0;

    for(int c:T[v]) {
        if(s >= a) break;

        if(low[c] >= tin[v]) continue;

        debug("fill {} (2)", c);

        s += S[c];
        fill_subtree(c, 0, dv);
    }

    assert(s >= a);

    forall(i, 0, N)
        if(dv[i] == -1) dv[i] = 1;
    
    return 1;
}

vi find_split(int n, int a, int b, int c, vi p, vi q) {

    N = n;

    vi x = {a,b,c};
    vi w = {1,2,3};
    sort(w.begin(), w.end(), [&](int a, int b){ return x[a-1]<x[b-1]; });

    a = x[w[0]-1], b=x[w[1]-1], c=x[w[2]-1];

    int M = p.size();

    G.resize(N);
    T.resize(N);

    S.resize(N);

    tin.resize(N);
    low.resize(N);

    forall(i, 0, M) {
        G[p[i]].push_back(q[i]);
        G[q[i]].push_back(p[i]);
    }

    vb V(N);

    int t = 0;

    int cand = -1;
    int ty = -1;

    auto dfs1 = [&](auto dfs1, int v, int p) -> bool {
        if(V[v]) return 0;
        V[v] = 1;

        if(p!=-1) T[p].push_back(v);
        
        low[v] = tin[v] = t++;

        S[v] = 1;

        for(int c:G[v]) {
            if(V[c]) { // back edge
                low[v] = min(low[v], low[c]);
                continue;
            }

            dfs1(dfs1, c, v);
            low[v] = min(low[v], low[c]);

            S[v] += S[c];
        }

        if(cand == -1) {

            if(S[v]>=a && S[v]<=N-a) {
                cand = v;
                ty = 1;
            }

            else if(S[v] > N-a) {
                cand = v;
                ty = 2;
            }
        }

        return 1;
    };

    dfs1(dfs1, 0, -1);

    debug("cand {} ty {}", cand, ty);

    assert(cand != -1);

    dv.assign(N, -1);

    bool ret;

    if(ty == 1) {
        ret = divide_ty1(cand, a);
    } else {
        ret = divide_ty2(cand, a);
    }

    if(!ret) {
        ans.assign(N, 0);
        return ans;
    }

    debug("dv {}", dv);

    ans.assign(N, -1);

    auto fill = [&](auto fill, int v, int x, int dvi, int &k) -> void {
        if(ans[v] != -1 || k==0 || dv[v]!=dvi) return;

        ans[v] = x;
        k--;

        for(int c:G[v])
            fill(fill, c, x, dvi, k);
    };

    int va=-1, vb=-1;

    forall(i, 0, N) {
        if(dv[i] == 0 && va==-1)
            va=i;
        
        if(dv[i] == 1 && vb==-1)
            vb=i;
    }

    int k = a;

    fill(fill, va, w[0], 0, k);
    assert(k==0);

    k = b;
    fill(fill, vb, w[1], 1, k);
    assert(k==0);

    forall(i, 0, N)
        if(ans[i] == -1) ans[i] = w[2];

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