Submission #1336939

#TimeUsernameProblemLanguageResultExecution timeMemory
1336939liptonekKeys (IOI21_keys)C++20
0 / 100
133 ms237604 KiB
#include <bits/stdc++.h>
using namespace std;

struct Component 
{
    vector<int> nodes;
    set<int> owned;
    map<int,vector<int>> pending;
    queue<int> ready;
};

int parent[300005];

Component comps[300005];

int find(int i) 
{
    int root=i;

	while(parent[root]!=root) 
	{
		root=parent[root];
	}

    while(parent[i]!=root) 
	{
        int next=parent[i];
    
		parent[i]=root;
        i=next;
    }
    
	return root;
}

int merge(int u, int v) 
{
    u=find(u);
    v=find(v);

	if(u==v) 
	{
		return u;
	}
    
    if(comps[u].nodes.size()<comps[v].nodes.size()) 
	{
		swap(u,v);
	}

    parent[v]=u;
    
    for(int node : comps[v].nodes) 
	{
        comps[u].nodes.push_back(node);
    }
    
	comps[v].nodes.clear();
    
    for(int k : comps[v].owned) 
	{
        if(comps[u].owned.find(k)==comps[u].owned.end()) 
		{
            comps[u].owned.insert(k);
        
			auto it=comps[u].pending.find(k);
        
			if(it != comps[u].pending.end()) 
			{
                for(int target : it->second) 
				{
                    comps[u].ready.push(target);
                }
                
				comps[u].pending.erase(it);
            }
        }
    }

    comps[v].owned.clear();
    
    for(auto& entry : comps[v].pending) 
	{
        int k=entry.first;
    
		if(comps[u].owned.count(k)) 
		{
            for(int target : entry.second) 
			{
                comps[u].ready.push(target);
            }
        } 
		else 
		{
            vector<int>& vec=comps[u].pending[k];
        
			if(vec.size()<entry.second.size()) 
			{
				swap(vec,entry.second);
			}
        
			vec.insert(vec.end(),entry.second.begin(),entry.second.end());
        }
    }

    comps[v].pending.clear();
    
    while(!comps[v].ready.empty()) 
	{
        comps[u].ready.push(comps[v].ready.front());
        comps[v].ready.pop();
    }
    
    return u;
}

vector<int> find_reachable(vector<int> r, vector<int> u, vector<int> v, vector<int> c) 
{
    int n=r.size();
    int m=u.size();
    
    vector<vector<pair<int,int>>> adj(n);

	for(int i=0; i<m; i++) 
	{
        adj[u[i]].push_back({c[i],v[i]});
        adj[v[i]].push_back({c[i],u[i]});
    }
    
    for(int i=0; i<n; i++) 
	{
        parent[i]=i;
        comps[i].nodes={i};
        comps[i].owned={r[i]};
    
		comps[i].pending.clear();
    
		while(!comps[i].ready.empty()) 
		{
			comps[i].ready.pop();
		}
        
        for(auto& edge : adj[i]) 
		{
            if(edge.first==r[i]) 
			{
                comps[i].ready.push(edge.second);
            } 
			else 
			{
                comps[i].pending[edge.first].push_back(edge.second);
            }
        }
    }
    
    vector<bool> used(n,false);   
    vector<bool> active(n,false); 
    vector<int> sink;        
    
    for(int i=0; i<n; i++) 
	{
        int root=find(i);
    
		if(used[root]) 
		{
			continue;
		}
        
        vector<int> path;
        
		used[root]=true;
        active[root]=true;
        
		path.push_back(root);
        
        while(!path.empty()) 
		{
            int p=path.back();
            int next=-1;
            
            while(!comps[p].ready.empty()) 
			{
                int target=comps[p].ready.front();
            
				comps[p].ready.pop();
            
				int tr=find(target);
            
				if(tr!=p) 
				{
                    next=tr;
                    break;
                }
            }
            
            if(next!=-1) 
			{
                if(active[next]) 
				{
                    while(path.back()!=next) 
					{
                        int w=path.back();
                        path.pop_back();
                    
						active[w]=false;
                        next=merge(next,w);
                    }
                    
					path.pop_back();
                    path.push_back(next);
                    
					active[next]=true;
                } 
				else if(used[next]) 
				{
                    for(int w : path) 
					{
						active[w]=false;
					}

                    path.clear();
                } 
				else 
				{
                    used[next]=true;
                    active[next]=true;

					path.push_back(next);
                }
            } 
			else 
			{
                sink.push_back(p);

				for(int w : path) 
				{
					active[w]=false;
				}

				path.clear();
            }
        }
    }
    
    int reachable=n+1;

	for(int root : sink) 
	{
        reachable=min(reachable,(int)comps[root].nodes.size());
    }
    
    vector<int> ans(n,0);

	for(int root : sink) 
	{
        if((int)comps[root].nodes.size()==reachable) 
		{
            for(int node : comps[root].nodes) 
			{
                ans[node]=1;
            }
        }
    }
    
    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...