Submission #865047

#TimeUsernameProblemLanguageResultExecution timeMemory
865047xiaowuc1Factories (JOI14_factories)C++17
100 / 100
4373 ms329952 KiB
#include <algorithm> #include <array> #include <bitset> #include <cassert> #include <chrono> #include <complex> #include <cstring> #include <functional> #include <iomanip> #include <iostream> #include <map> #include <numeric> #include <queue> #include <random> #include <set> #include <stack> #include <unordered_map> #include <vector> using namespace std; // BEGIN NO SAD #define rep(i, a, b) for(int i = a; i < (b); ++i) #define trav(a, x) for(auto& a : x) #define all(x) x.begin(), x.end() #define sz(x) (int)(x).size() #define mp make_pair #define pb push_back #define eb emplace_back #define lb lower_bound #define ub upper_bound typedef vector<int> vi; #define f first #define s second #define derr if(0) cerr void __print(int x) {cerr << x;} void __print(long x) {cerr << x;} void __print(long long x) {cerr << x;} void __print(unsigned x) {cerr << x;} void __print(unsigned long x) {cerr << x;} void __print(unsigned long long x) {cerr << x;} void __print(float x) {cerr << x;} void __print(double x) {cerr << x;} void __print(long double x) {cerr << x;} void __print(char x) {cerr << '\'' << x << '\'';} void __print(const char *x) {cerr << '\"' << x << '\"';} void __print(const string &x) {cerr << '\"' << x << '\"';} void __print(bool x) {cerr << (x ? "true" : "false");} template<typename T, typename V> void __print(const pair<T, V> &x) {cerr << '{'; __print(x.first); cerr << ", "; __print(x.second); cerr << '}';} template<typename T> void __print(const T &x) {int f = 0; cerr << '{'; for (auto &i: x) cerr << (f++ ? ", " : ""), __print(i); cerr << "}";} void _print() {cerr << "]\n";} template <typename T, typename... V> void _print(T t, V... v) {__print(t); if (sizeof...(v)) cerr << ", "; _print(v...);} #define debug(x...) cerr << "\e[91m"<<__func__<<":"<<__LINE__<<" [" << #x << "] = ["; _print(x); cerr << "\e[39m" << flush; // END NO SAD template<class Fun> class y_combinator_result { Fun fun_; public: template<class T> explicit y_combinator_result(T &&fun): fun_(std::forward<T>(fun)) {} template<class ...Args> decltype(auto) operator()(Args &&...args) { return fun_(std::ref(*this), std::forward<Args>(args)...); } }; template<class Fun> decltype(auto) y_combinator(Fun &&fun) { return y_combinator_result<std::decay_t<Fun>>(std::forward<Fun>(fun)); } template<class T> bool updmin(T& a, T b) { if(b < a) { a = b; return true; } return false; } template<class T> bool updmax(T& a, T b) { if(b > a) { a = b; return true; } return false; } typedef int64_t ll; typedef pair<int, int> pii; mt19937 g1(0x48); ll get_random_int(ll a, ll b) { return uniform_int_distribution<ll>(a, b)(g1); } struct koosaga { vector<vector<ll>> centroidtovertexdist; // <id, depth> vector<vector<int>> centroidtochildidx; // <id, depth> vector<vector<int>> centroidtochildcentroid; int n; int rootcentroid; ll qry(int currcentroid, int depth, vector<int>& lhs, vector<int>& rhs) { if(sz(lhs) == 0 || sz(rhs) == 0) return 1e18; ll ret = 1e18; ll lv = 1e18; ll rv = 1e18; { sort(all(lhs), [&](int a, int b) -> bool { return centroidtochildidx[a][depth] < centroidtochildidx[b][depth]; }); sort(all(rhs), [&](int a, int b) -> bool { return centroidtochildidx[a][depth] < centroidtochildidx[b][depth]; }); } int li = 0, ri = 0; if(lhs[li] == currcentroid) lv = 0, li++; if(rhs[ri] == currcentroid) rv = 0, ri++; while(li < sz(lhs) || ri < sz(rhs)) { int choice = 1e9; if(li < sz(lhs)) updmin(choice, centroidtochildidx[lhs[li]][depth]); if(ri < sz(rhs)) updmin(choice, centroidtochildidx[rhs[ri]][depth]); assert(choice >= 0); int nli = li; vector<int> nlv, nrv; while(nli < sz(lhs) && centroidtochildidx[lhs[nli]][depth] == choice) { nlv.pb(lhs[nli]); updmin(lv, centroidtovertexdist[lhs[nli++]][depth]); } int nri = ri; while(nri < sz(rhs) && centroidtochildidx[rhs[nri]][depth] == choice) { nrv.pb(rhs[nri]); updmin(rv, centroidtovertexdist[rhs[nri++]][depth]); } updmin(ret, qry(centroidtochildcentroid[currcentroid][choice], depth+1, nlv, nrv)); li = nli; ri = nri; } return min(lv+rv, ret); } koosaga(){} koosaga(vector<array<int, 3>>& e) { n = sz(e) + 1; vector<int> nxtid(2*n-2, -1); vector<int> startid(n, -1); vector<int> to(2*n-2, -1); vector<int> weights(2*n-2); for(int i = 0; i < sz(e); i++) { auto [a, b, w] = e[i]; to[2*i] = b; weights[2*i] = w; nxtid[2*i] = startid[a]; startid[a] = 2*i; to[2*i+1] = a; weights[2*i+1] = w; nxtid[2*i+1] = startid[b]; startid[b] = 2*i+1; } centroidtovertexdist.resize(n); centroidtochildidx.resize(n); centroidtochildcentroid.resize(n); rootcentroid = -1; vector<int> seen(n); vector<int> par(n); vector<int> treesz(n); vector<bool> processed(n); int centroiditer = 0; vector<int> postorder(n); vector<array<ll, 3>> q(n); auto init = y_combinator([&](auto initself, const int srcv) -> int { assert(!processed[srcv]); auto getcentroid = [&]() -> int { seen[srcv] = centroiditer++; int ql = 0; int qr = 0; postorder[qr++] = srcv; while(ql < qr) { int curr = postorder[ql++]; treesz[curr] = 1; for(int id = startid[curr]; id >= 0; id = nxtid[id]) { int nv = to[id]; if(!processed[nv] && seen[nv] != centroiditer) { seen[nv] = centroiditer; par[nv] = curr; postorder[qr++] = nv; } } } int totnodes = qr; for(int i = qr-1; i > 0; i--) { treesz[par[postorder[i]]] += treesz[postorder[i]]; if(2*treesz[postorder[i]] >= totnodes) return postorder[i]; } return srcv; }; int centroid = getcentroid(); centroidtochildidx[centroid].pb(-1); int childidx = 0; { int ql = 0; int qr = 0; q[qr++] = {centroid, 0, -1}; while(ql < qr) { auto [v, w, p] = q[ql++]; centroidtovertexdist[v].pb(w); if(p == centroid) centroidtochildidx[v].pb(childidx++); else if(p >= 0) centroidtochildidx[v].pb(centroidtochildidx[p].back()); for(int id = startid[v]; id >= 0; id = nxtid[id]) { int nv = to[id]; int nw = weights[id]; if(processed[nv] || nv == p) continue; q[qr++] = {nv, w+nw, v}; } } } processed[centroid] = true; for(int id = startid[centroid]; id >= 0; id = nxtid[id]) { int nv = to[id]; if(processed[nv]) continue; centroidtochildcentroid[centroid].pb(initself(nv)); } return centroid; }); rootcentroid = init(get_random_int(0, n-1)); } }; koosaga koo; void Init(int N, int A[], int B[], int D[]){ vector<array<int, 3>> edges(N-1); for(int i = 0; i < N-1; i++) edges[i] = {A[i], B[i], D[i]}; koo = koosaga(edges); } long long Query(int S, int X[], int T, int Y[]){ vector<int> lhs(S), rhs(T); for(int i = 0; i < S; i++) lhs[i] = X[i]; for(int i = 0; i < T; i++) rhs[i] = Y[i]; return koo.qry(koo.rootcentroid, 0, lhs, rhs); } /* void solve() { int n, q; cin >> n >> q; int *A = (int*)malloc(sizeof(int) * (n - 1)); int *B = (int*)malloc(sizeof(int) * (n - 1)); int *D = (int*)malloc(sizeof(int) * (n - 1)); for(int a = 0; a < n - 1; a++){ cin >> A[a] >> B[a] >> D[a]; } Init(n, A, B, D); while(q--) { int S, T; cin >> S >> T; int *X = (int*)malloc(sizeof(int) * S); int *Y = (int*)malloc(sizeof(int) * T); for(int b = 0; b < S; b++) cin >> X[b]; for(int b = 0; b < T; b++) cin >> Y[b]; cout << Query(S, X, T, Y) << "\n"; } } // what would chika do // are there edge cases (N=1?) // are array sizes proper (scaled by proper constant, for example 2* for koosaga tree) // integer overflow? // DS reset properly between test cases // are you doing geometry in floating points // are you not using modint when you should int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); solve(); } */
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...