Submission #289909

#TimeUsernameProblemLanguageResultExecution timeMemory
289909MarcoMeijerSplit the Attractions (IOI19_split)C++14
100 / 100
218 ms21880 KiB
#include <bits/stdc++.h>
#include "split.h"
using namespace std;

//macros
typedef long long ll;
typedef pair<int, int> ii;
typedef pair<ll, ll> lll;
typedef tuple<int, int, int> iii;
typedef vector<int> vi;
typedef vector<ii> vii;
typedef vector<iii> viii;
typedef vector<ll> vll;
typedef vector<lll> vlll;
#define REP(a,b,c) for(int a=int(b); a<int(c); a++)
#define RE(a,c) REP(a,0,c)
#define RE1(a,c) REP(a,1,c+1)
#define REI(a,b,c) REP(a,b,c+1)
#define REV(a,b,c) for(int a=int(c-1); a>=int(b); a--)
#define FOR(a,b) for(auto& a:b)
#define INF 1e9
#define pb push_back
#define fi first
#define se second

const int MX = 1e5+10;

int n, m, a[3], SA[3];
int cnt[3];
int RSA[4];
vi adj[MX];
vi adjT[MX];
vi res;
bitset<MX> visited;
int sz[MX];
int cent;

void dfsTree(int u) {
    visited[u] = 1;
    FOR(v,adj[u]) if(!visited[v]) dfsTree(v), adjT[u].pb(v), adjT[v].pb(u);
}
void dfsSz(int u, int p) {
    sz[u] = 1;
    FOR(v,adjT[u]) if(v != p) dfsSz(v, u), sz[u]+=sz[v];
}
int dfsCentroid(int u, int p, int s) {
    FOR(v,adjT[u]) if(v != p && sz[v] >= s/2) return dfsCentroid(v,u,s);
    return u;
}

int comp[MX], compSZ[MX], compR[MX], compP[MX], compN=0;
void dfsComp(int u, int p) {
    comp[u] = compN;
    FOR(v,adjT[u]) if(v != p) dfsComp(v,u);
}
int getComp(int i) {return i==compP[i] ? i : compP[i] = getComp(compP[i]);}
bool isSameSet(int i, int j) {return getComp(i) == getComp(j);}
void unionSet(int i, int j) {
    if(isSameSet(i,j)) return;
    i=compP[i], j=compP[j];
    compSZ[i] = compSZ[j] = compSZ[i] + compSZ[j];
    if(compR[i] > compR[j]) {
        compP[j] = i;
    } else {
        compP[i] = j;
        if(compR[i] == compR[j]) compR[j]++;
    }
}

void dfsFirst(int u, int c, int numb) {
    if(res[u] != 0) return;
    if(cnt[numb] == a[SA[numb]]) return;
    cnt[numb]++;
    res[u] = numb+1;
    FOR(v,adj[u]) if(v != cent && getComp(comp[v]) == c) dfsFirst(v,c,numb);
}
void dfsSecond(int u, int numb) {
    if(res[u] != 0) return;
    if(cnt[numb] == a[SA[numb]]) return;
    cnt[numb]++;
    res[u] = numb+1;
    FOR(v,adj[u]) dfsSecond(v, numb);
}

vi find_split(int N, int A, int B, int C, vi P, vi Q) {
    n=N; a[0]=A; a[1]=B; a[2]=C;
    RE(i,3) SA[i]=i;
    sort(SA,SA+3,[](int i, int j) {
        return a[i]<a[j];
    });
    res.assign(n,0);
    m=P.size();
    RE(i,m) {
        adj[P[i]].pb(Q[i]);
        adj[Q[i]].pb(P[i]);
    }
    visited.reset(); dfsTree(1);
    dfsSz(1, -1);
    cent = dfsCentroid(1, -1, sz[1]);
    dfsSz(cent, -1);
    FOR(u,adjT[cent]) {
        compSZ[compN] = sz[u];
        dfsComp(u,cent);
        compN++;
    }
    RE(i,compN) compP[i]=i, compR[i]=1;
    RE(i,m) {
        if(P[i] == cent || Q[i] == cent) continue;
        int u = getComp(comp[P[i]]);
        int v = getComp(comp[Q[i]]);
        if(compSZ[u] < a[SA[0]] && compSZ[v] < a[SA[0]])
            unionSet(u,v);
    }

    int firstComp = -1;
    RE(i,compN)
        if(compSZ[i] >= a[SA[0]])
            firstComp = i;
    if(firstComp == -1) return res;

    RE(i,3) cnt[i] = 0;
    RE(i,n) if(i != cent && compSZ[getComp(comp[i])] >= a[SA[0]]) {
        dfsFirst(i, getComp(comp[i]),0);
        break;
    }
    dfsSecond(cent,1);
    RE(i,n) if(res[i] == 0) res[i] = 3;
    RE(i,n) res[i] = SA[res[i]-1]+1;

	return res;
}
#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...