Submission #752656

#TimeUsernameProblemLanguageResultExecution timeMemory
752656Ronin13열쇠 (IOI21_keys)C++17
100 / 100
1296 ms207852 KiB
#include <vector>
#include <bits/stdc++.h>
#define ll long long
#define ull unsigned ll
#define f first
#define s second
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pb push_back
#define epb emplace_back
using namespace std;

const int nmax = 500001;
int p[nmax][2];
int sz[nmax][2];

void make_set(int v, int ind){
    p[v][ind] = v;
    sz[v][ind] = 1;
}

int find_set(int v, int ind){
    if(p[v][ind] == v){
        return v;
    }
    return p[v][ind] = find_set(p[v][ind], ind);
}

void union_sets(int a, int b, int ind){
     a = find_set(a, ind);
     b = find_set(b, ind);
     if(a == b)
        return;
     p[b][ind] = a;
     sz[a][ind] += sz[b][ind];
}
vector <pii> empt;
struct node{

    map <int,int>mp;
    set <int> st;
    vector <vector <pii> > edg;

    int tot = 0;
    int sz;
    int p;
    node(){
    }
    node(int x){
        sz = 1;
        p = x;
        tot = 0;
        edg.pb(empt);
    }
    void add_edge(int x, int c){
        tot++;
        if(!mp[c]){
            mp[c] = edg.size();
            edg.pb(empt);
        }
        edg[mp[c]].pb({x, c});
    }
    void add_color(int x){
        st.insert(x);
    }
    int get_edge(int v){
        while(!st.empty()){
            int x = *st.begin();
            int o = mp[x];
            if(!o) {st.erase(st.begin());continue;}
            while(!edg[o].empty()){
                int u = edg[o].back().f;
                edg[o].pop_back();
                if(find_set(u, 1) != find_set(v, 1)){
                    return u;
                }
            }
            st.erase(st.begin());
        }
        return -1;
    }
}vert[nmax];

void merg(int u, int v){
    u = find_set(u, 1);
    v = find_set(v, 1);
    if(vert[v].tot > vert[u].tot){
        swap(vert[u].edg, vert[v].edg);
        swap(vert[u].tot, vert[v].tot);
        swap(vert[u].mp, vert[v].mp);
        swap(vert[u].st, vert[v].st);
    }
    for(auto x : vert[v].edg){
        for(auto to : x){
            vert[u].add_edge(to.f, to.s);
        }
    }
    for(auto x : vert[v].st){
        vert[u].st.insert(x);
    }
    union_sets(u, v, 1);
}

set <int> roots;
int ans = 1e9;
set <int> good;
bool upd(){
    if(roots.empty()){
        return false;
    }
    while(!roots.empty()){
        int x = *roots.begin();
        int val = vert[x].get_edge(x);
        if(val == -1){
            if(sz[x][1] < ans){
                good.clear();
                ans = sz[x][1];
                good.insert(x);
            }
            else if(sz[x][1] == ans){
                good.insert(x);
            }
            roots.erase(roots.begin());
        }
        else{
            if(find_set(x, 0) == find_set(val , 0)){
                while(find_set(val, 1) != find_set(x, 1)){
                    int xx = find_set(val, 1);
                    merg(x, val);
                    val = vert[xx].p;
                }

            }
            else{
                roots.erase(roots.begin());
                vert[x].p = val;
                union_sets(val, x, 0);
            }
            return true;
        }

    }
    return false;
}

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();
	for(int i = 0; i < n; i++){
        vert[i] = {i};
        vert[i].add_color(r[i]);
        make_set(i, 0);
        make_set(i, 1);

	}
	for(int i = 0; i < u.size(); i++){
        vert[u[i]].add_edge(v[i], c[i]);
        vert[v[i]].add_edge(u[i], c[i]);
	}
	for(int i = 0; i < n; ++i)
        roots.insert(i);
	while(upd()){}
	vector <int> ans(n);
	for(int i = 0; i < n; ++i){
        if(good.find(find_set(i, 1)) != good.end())
            ans[i] = 1;
	}
	return ans;
}

Compilation message (stderr)

keys.cpp: In function 'std::vector<int> find_reachable(std::vector<int>, std::vector<int>, std::vector<int>, std::vector<int>)':
keys.cpp:155:19: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  155 |  for(int i = 0; i < u.size(); i++){
      |                 ~~^~~~~~~~~~
#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...