제출 #335026

#제출 시각아이디문제언어결과실행 시간메모리
335026Plurm도서관 (JOI18_library)C++11
100 / 100
537 ms748 KiB
#include <bits/stdc++.h> #include "library.h" using namespace std; int p[1024]; int fn(int x){ if(p[x] == -1) return x; else return p[x] = fn(p[x]); } bool un(int x, int y){ x = fn(x); y = fn(y); if(x == y) return false; p[x] = y; return true; } int queryRange(int L, int R, int N, int sp = -1){ bitset<1024> s; vector<int> M(N); for(int i = L; i <= R; i++){ s[fn(i)] = true; } if(sp != -1) s[fn(sp)] = true; for(int i = 0; i < N; i++){ if(s[fn(i)]) M[i] = 1; else M[i] = 0; } return Query(M); } int countRange(int L, int R, int sp = -1){ bitset<1024> s; for(int i = L; i <= R; i++){ s[fn(i)] = true; } if(sp != -1) s[fn(sp)] = true; return s.count(); } int LeftTurn(int L, int N){ // L -> x duplicates // L -> x-1 does not duplicate vector<int> active; bitset<1024> s; for(int i = L; i < N; i++){ int cur = fn(i); if(!s[cur]){ active.push_back(i); s[cur] = true; } } if(queryRange(L, N-1, N, L) == countRange(L, N-1, L)) return -1; int lo = 0; int hi = active.size()-1; int mid; while(lo < hi){ mid = (lo + hi)/2; if(queryRange(L, active[mid], N, L) == countRange(L, active[mid], L)) lo = mid+1; else hi = mid; } return active[lo]; } int RightTurn(int R, int N){ // x <- R duplicates // x+1 <- R does not duplicate vector<int> active; bitset<1024> s; for(int i = R; i >= 0; i--){ int cur = fn(i); if(!s[cur]){ active.push_back(i); s[cur] = true; } } reverse(active.begin(), active.end()); if(queryRange(0, R, N, R) == countRange(0, R, R)) return -1; int lo = 0; int hi = active.size()-1; int mid; while(lo < hi){ mid = (lo + hi + 1)/2; if(queryRange(active[mid], R, N, R) == countRange(active[mid], R, R)) hi = mid-1; else lo = mid; } return active[lo]; } vector<int> g[1024]; void addEdge(int u, int v){ g[u].push_back(v); g[v].push_back(u); } int findLeaf(int u, int p = -1){ for(int v : g[u]){ if(v == p) continue; return findLeaf(v, u); } return u; } pair<int,int> findExtremum(int u){ if(g[u].size() > 1){ return make_pair(findLeaf(g[u][0], u), findLeaf(g[u][1], u)); }else if(g[u].size() == 1){ return make_pair(u, findLeaf(g[u][0], u)); }else{ return make_pair(u, u); } } bool checkPair(int l, int r, int N){ vector<int> M(N); fill(M.begin(), M.end(), 0); M[l] = M[r] = 1; return Query(M) == 1; //return g[l].size() < 2 && g[r].size() < 2; } void Solve(int N) { memset(p, -1, sizeof(p)); vector<int> M(N); for(int i = 1; i < N; i++){ int l = LeftTurn(0, N); int r = RightTurn(l, N); int l1, l2; tie(l1, l2) = findExtremum(l); int r1, r2; tie(r1, r2) = findExtremum(r); if(checkPair(l1, r1, N)){ l = l1; r = r1; }else if(checkPair(l1, r2, N)){ l = l1; r = r2; }else if(checkPair(l2, r1, N)){ l = l2; r = r1; }else if(checkPair(l2, r2, N)){ l = l2; r = r2; } un(l, r); addEdge(l, r); } int last = -1; int leaf = findLeaf(0); vector<int> ans; for(int i = 0; i < N; i++){ ans.push_back(leaf+1); int nxt = -1; for(int v: g[leaf]){ if(v != last) nxt = v; } last = leaf; leaf = nxt; } Answer(ans); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...