Submission #435915

#TimeUsernameProblemLanguageResultExecution timeMemory
435915frodakcinKeys (IOI21_keys)C++17
100 / 100
2136 ms164904 KiB
#include <cassert> #include <cstring> #include <stack> #include <vector> #include <set> template<typename T> bool ckmax(T& a, const T& b) {return b>a?a=b,1:0;} template<typename T> bool ckmin(T& a, const T& b) {return b<a?a=b,1:0;} const int MN = 3e5+10; int N, M; struct edge { public: int n, w; bool operator < (const edge& o) const {return w < o.w || !(o.w < w) && n < o.n;} }; struct DSU { public: std::vector<int> p, r; DSU(int N): p(N, -1), r(N, 0) {} int find(int n) {return p[n]==-1 ? n : p[n]=find(p[n]);} bool merge(int a, int b) { a=find(a), b=find(b); assert(a!=b); if(a==b) return 0; if(r[a]<r[b]) std::swap(a,b); p[b]=a, r[a]+=r[a]==r[b], r[b]=-1; return 1; } }; DSU dsu(MN); std::set<edge> a[MN]; std::set<int> col[MN]; std::vector<int> todo[MN]; int d[MN], l[MN], ctr, cc, sz[MN]; // scc bool in_stack[MN], out[MN], good[MN]; std::stack<int> stk; std::vector<int> g[MN]; void dfs(int n) { d[n] = l[n] = ctr++; stk.push(n); in_stack[n] = 1; for(;!todo[n].empty();) { int x=todo[n].back(); todo[n].pop_back(); if(d[x] == -1) { dfs(x), ckmin(l[n], l[x]); if(!in_stack[x]) out[n]=1; } else if(in_stack[x]) ckmin(l[n], d[x]); else out[n]=1; int u=dsu.find(n), v=dsu.find(x); if(u!=v) { dsu.merge(u, v); if(dsu.p[v] == -1) std::swap(u,v); //v -> u if(col[u].size()+a[u].size() < col[v].size()+a[v].size()) col[u].swap(col[v]), a[u].swap(a[v]); for(int c:col[v]) if(col[u].insert(c).second) { auto it=a[u].lower_bound({-1,c}); for(;it != a[u].end() && it->w == c;it=a[u].erase(it)) todo[n].push_back(it->n); } for(auto c:a[v]) if(col[u].find(c.w) != col[u].end()) todo[n].push_back(c.n); else a[u].insert(c); col[v].clear(); a[v].clear(); } /* printf("MERGE %d - %d\n", n, x); printf("COL: "); for(auto z:col[dsu.find(n)]) printf("%d ", z); printf("\n"); printf("EDG: "); for(auto z:a[dsu.find(n)]) printf("(%d,%d) ", z.n, z.w); printf("\n"); */ } if(l[n] == d[n]) { ++cc; good[cc]=1; for(;;) { int x=stk.top(); stk.pop(); ++sz[cc]; if(out[x]) good[cc]=0; g[cc].push_back(x); in_stack[x] = 0; if(x == n) break; } } } std::vector<int> find_reachable(std::vector<int> r, std::vector<int> u, std::vector<int> v, std::vector<int> c) { memset(d, -1, sizeof d); N = r.size(); M = u.size(); std::vector<int> ans(r.size(), 0); for(int i=0;i<M;++i) { a[u[i]].insert({v[i], c[i]}); a[v[i]].insert({u[i], c[i]}); } for(int i=0;i<N;++i) { col[i].insert(r[i]); auto it=a[i].lower_bound({-1,r[i]}); for(;it != a[i].end() && it->w == r[i];it = a[i].erase(it)) todo[i].push_back(it->n); } for(int i=0;i<N;++i) { if(d[i] == -1) dfs(i); } int msz=N; for(int i=1;i<=cc;++i) if(good[i]) ckmin(msz, sz[i]); for(int i=1;i<=cc;++i) if(good[i] && sz[i] == msz) for(int x:g[i]) ans[x]=1; return ans; }

Compilation message (stderr)

keys.cpp: In member function 'bool edge::operator<(const edge&) const':
keys.cpp:17:71: warning: suggest parentheses around '&&' within '||' [-Wparentheses]
   17 |   bool operator < (const edge& o) const {return w < o.w || !(o.w < w) && n < o.n;}
      |                                                            ~~~~~~~~~~~^~~~~~~~~~
#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...