Submission #1210658

#TimeUsernameProblemLanguageResultExecution timeMemory
1210658garam1732Keys (IOI21_keys)C++20
9 / 100
285 ms107044 KiB
#include <bits/stdc++.h>
using namespace std;

#define ff first
#define ss second
#define bl ' '
#define endl '\n'
#define all(v) (v).begin(), (v).end()
#define comp(v) (v).erase(unique(all(v)), (v).end())
#define lbd(v,x) lower_bound(all(v), (x))-(v).begin()
#define ubd(v,x) upper_bound(all(v), (x))-(v).begin()

typedef long long ll;
typedef pair<int, int> pi;
typedef pair<pi, int> pii;
typedef pair<int, pi> ipi;
typedef pair<pi, pi> pipi;
typedef pair<ll, ll> pll;

const int MAXN = 100100*3;
const ll MOD = 998244353;
const ll INF = 1e16;

vector<pi> adj[MAXN];
int nx[MAXN], idx[MAXN];
//vector<int> pv[MAXN];

set<int> col[MAXN];
set<pi> edge[MAXN];
int cnt[MAXN];

vector<int> cnct, pnt; 
int root(int x, vector<int>& par) { return par[x]==x?x:par[x]=root(par[x], par); }
void merge(int x, int y, vector<int>& par) {
    x = root(x, par), y = root(y, par);
    if(x^y) par[y] = x;
}

void merge_stl(int a, int b, bool flag) {
    merge(a, b, pnt);

    if(flag) {
        nx[a] = -1;
        vector<pi> tmp;
        for(int c : col[b]) {
            while(nx[a]==-1) {
                auto it = edge[a].lower_bound(pi(c,0));
                if(it == edge[a].end() || it->ff != c) break;
                
                int x = it->ss;
                if(root(x, pnt)==a || root(x, pnt)==b) {
                    edge[a].erase(it); continue;
                }

                nx[a] = x;
            }
        } for(auto [c,x] : edge[b]) { if(nx[a]!=-1) break;
            if(root(x,pnt)==a || root(x,pnt)==b) {
                tmp.push_back(pi(c,x)); continue;
            }

            if(col[a].find(c)!=col[a].end()) {
                nx[a] = x; break;
            }
        } for(auto x:tmp) edge[b].erase(x);
    }

    cnt[a] += cnt[b];
    for(int x : col[b]) {
        col[a].insert(x);
    } for(auto x : edge[b]) {
        edge[a].insert(x);
    } col[b].clear(); edge[b].clear();
}

queue<vector<int> > cycle;
vector<pi> cand;
vector<int> ans;

int vst[MAXN]; // -1: already vst, 0: not vst, 1: current vst
vector<int> track;
void dfs(int here) {
    vst[here] = 1;
    track.push_back(here);

    int there = nx[here];
    if(there == -1) return;
    if(vst[there] == -1) return;
    if(vst[there] == 1) {
        vector<int> v;
        int i=0; while(track[i]^there) i++;
        for(; i<track.size(); i++) v.push_back(track[i]);
        cycle.push(v); return;
    } dfs(there);
}

std::vector<int> find_reachable(std::vector<int> r, std::vector<int> u, std::vector<int> v, std::vector<int> c) {
	int n = r.size(), m = u.size();
    for(int i=0; i<m; i++) {
        adj[u[i]].push_back(pi(v[i], c[i]));
        adj[v[i]].push_back(pi(u[i], c[i]));
    } for(int i=0; i<n; i++) {
        col[i].insert(r[i]);
        cnt[i] = 1;

        for(auto [j,w] : adj[i]) {
            edge[i].insert(pi(w, j));
        }
    }

    cnct.resize(n); pnt.resize(n); ans.resize(n);
    for(int i=0; i<n; i++) cnct[i] = pnt[i] = i;

    // nx init
    bool chk = 0;
    memset(nx, -1, sizeof nx);
    for(int i=0; i<n; i++) {
        for(int &j = idx[i]; j<adj[i].size(); j++) {
            int x = adj[i][j].ff, w = adj[i][j].ss;
            if(w == r[i]) {
                nx[i] = x; //pv[x].push_back(i);
                merge(i, nx[i], cnct); break;
            }
        } if(nx[i] == -1) {
            chk=1; ans[i]=1;
        }
    } if(chk) return ans;

    // find cycle
    for(int i=0; i<n; i++) {
        if(!vst[i]) {
            track.clear();
            dfs(i);
            for(int x:track) vst[x]=-1;
        }
    }

    while(cycle.size()) {
        // union cycle, update new nx
        vector<int> v = cycle.front(); cycle.pop();
        for(int i=1; i<v.size(); i++) {
            if(col[v[0]].size()+edge[v[0]].size() < col[v[i]].size()+edge[v[i]].size()) swap(v[0], v[i]);
            merge_stl(v[0], v[i], i+1==v.size());
        }

        if(nx[v[0]] == -1) {
            cand.push_back(pi(cnt[v[0]], v[0]));
            continue;
        }

        // update new cycle
        vector<int> tmp;
        vector<int> new_cycle;
        int x = root(v[0], cnct), y = root(nx[v[0]], cnct);
        if(x == y) {
            new_cycle.push_back(v[0]);
            for(int here = root(nx[v[0]], pnt); here != v[0]; here=root(nx[here], pnt))
                new_cycle.push_back(here);
        } else {
            merge(x, y, cnct);
        }

        // push new cycle
        if(new_cycle.size() > 1) cycle.push(new_cycle);
    }
    
    // return smallest root
    sort(all(cand)); int mn = cand[0].ff;
    for(auto x:cand) { assert(pnt[x.ss]==x.ss);
        if(x.ff==mn) ans[x.ss]=1;
    } for(int i=0; i<n; i++) {
        ans[i] = ans[root(i, pnt)];
    }

	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...