Submission #296828

#TimeUsernameProblemLanguageResultExecution timeMemory
296828rqiSplit the Attractions (IOI19_split)C++14
100 / 100
293 ms29004 KiB
#include "split.h" #include <bits/stdc++.h> using namespace std; typedef vector<int> vi; typedef pair<int, int> pi; typedef vector<pi> vpi; #define pb push_back #define sz(x) (int)(x).size() #define mp make_pair #define f first #define s second #define all(x) begin(x), end(x) const int mx = 100005; struct DSU{ vi e; void init(int n){ e = vi(n, -1); } int get(int a){ if(e[a] < 0) return a; e[a] = get(e[a]); return e[a]; } int getSz(int a){ return -e[get(a)]; } bool sameSet(int a, int b){ return get(a) == get(b); } bool unite(int a, int b){ a = get(a); b = get(b); if(a == b) return 0; if(-e[a] < -e[b]) swap(a, b); //a now has bigger size e[a]+=e[b]; e[b] = a; return 1; } }; int n, a, b, c; vi L; vi res; vi oadj[mx]; vi tadj[mx]; //tree edges DSU dsu; vpi extr; int sub[mx]; void genSub(int node, int prv = -1){ sub[node] = 1; for(auto u: tadj[node]){ if(u == prv) continue; genSub(u, node); sub[node]+=sub[u]; } } int getCen(int node, int prv = -1){ for(auto u: tadj[node]){ if(u == prv) continue; if(sub[u] >= n-sub[u]) return getCen(u, node); } return node; } int und[mx]; //underneath a node under cen vi rund[mx]; vi sadj[mx]; //adjacent things in cnt graph void genUnd(int node, int val, int prv = -1){ und[node] = val; rund[val].pb(node); for(auto u: tadj[node]){ if(u == prv) continue; genUnd(u, val, node); } } bool good[mx]; int curw; bool inSet[mx]; void getW(int node){ if(!good[node]) return; if(inSet[node]) return; if(curw >= L[0]) return; inSet[node] = 1; curw+=sub[node]; for(auto u: sadj[node]){ getW(u); } } int ocount = 0; void getOnes(int node){ if(und[node] == -1) return; if(!inSet[und[node]]) return; if(ocount >= L[0]) return; if(res[node] == 1) return; //cout << node << "\n"; ocount++; res[node] = 1; for(auto u: oadj[node]){ getOnes(u); } } int tcount = 0; void assign2(int node){ if(tcount >= L[1]) return; if(res[node] != 0) return; //cout << node << "\n"; res[node] = 2; tcount++; for(auto u: tadj[node]){ assign2(u); } } void adjustRes(){ vi to(4, 0); vi vals(4, 0); for(auto u: res) vals[u]++; vpi cnt1, cnt2; cnt1.pb(mp(a, 1)); cnt1.pb(mp(b, 2)); cnt1.pb(mp(c, 3)); cnt2.pb(mp(vals[1], 1)); cnt2.pb(mp(vals[2], 2)); cnt2.pb(mp(vals[3], 3)); sort(all(cnt1)); sort(all(cnt2)); for(int i = 0; i < 3; i++){ to[cnt2[i].s] = cnt1[i].s; } for(auto &u: res) u = to[u]; } bool visited[mx]; void crvisit(int node){ if(visited[node]) return; visited[node] = 1; for(auto u: oadj[node]){ if(res[node] == res[u]){ crvisit(u); } } } bool checkRes(){ vector<bool> works = vector<bool>(4, 1); for(int j = 1; j <= 3; j++){ for(int i = 0; i < n; i++){ if(res[i] == j){ crvisit(i); break; } } } for(int i = 0; i < n; i++){ if(!visited[i]){ works[res[i]] = 0; } } int cnt = 0; for(int j = 1; j <= 3; j++){ if(works[j]) cnt++; } if(cnt >= 2) return 1; return 0; } vi find_split(int _n, int _a, int _b, int _c, vi p, vi q) { n = _n, a = _a, b = _b, c = _c; L = vi{a, b, c}; sort(all(L)); res = vi(n, 0); dsu.init(n); for(int i = 0; i < sz(p); i++){ oadj[p[i]].pb(q[i]); oadj[q[i]].pb(p[i]); if(dsu.unite(p[i], q[i])){ tadj[p[i]].pb(q[i]); tadj[q[i]].pb(p[i]); //cout << p[i] << " " << q[i] << "\n"; } else{ extr.pb(mp(p[i], q[i])); //cout << p[i] << " " << q[i] << "\n"; } } genSub(0); int cen = getCen(0); und[cen] = -1; for(auto u: tadj[cen]){ genUnd(u, u, cen); //cout << u << " " << u << "\n"; } //cout << cen << "\n"; genSub(cen); dsu.init(n); for(auto u: tadj[cen]){ dsu.e[u] = -sub[u]; //cout << u << " " << dsu.e[u] << "\n"; } for(auto u: extr){ if(u.f == cen || u.s == cen) continue; dsu.unite(und[u.f], und[u.s]); sadj[und[u.f]].pb(und[u.s]); sadj[und[u.s]].pb(und[u.f]); // cout << und[u.f] << " " << und[u.s] << "\n"; } for(auto u: tadj[cen]){ if(dsu.getSz(u) >= L[0]){ //cout << u << "\n"; for(auto x: tadj[cen]){ if(dsu.sameSet(u, x)){ //cout << x << "\n"; good[x] = 1; } } curw = 0; getW(u); //for(int i = 0; i < n; i++) if(inSet[i]) cout << i << "\n"; ocount = 0; getOnes(u); assign2(cen); for(auto &u: res) if(u == 0) u = 3; // for(auto u: res) cout << u << " "; // cout << "\n"; adjustRes(); // for(auto u: res) cout << u << " "; // cout << "\n"; assert(checkRes()); return res; } } // for(auto u: res) cout << u << " "; // cout << "\n"; 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...