제출 #493035

#제출 시각아이디문제언어결과실행 시간메모리
493035Haruto810198Valley (BOI19_valley)C++17
100 / 100
937 ms116836 KiB
#include <bits/stdc++.h> using namespace std; #define int long long #define double long double #define FOR(i, l, r, d) for(int i=(l); i<=(r); i+=(d)) #define szof(x) ((int)(x).size()) #define vi vector<int> #define pii pair<int, int> #define F first #define S second #define pb push_back #define eb emplace_back #define mkp make_pair const int INF = INT_MAX; const int LNF = INF*INF; const int MOD = 1000000007; const int mod = 998244353; const double eps = 1e-12; //#pragma GCC optimize("Ofast") //#pragma GCC optimize("unroll-loops") const int MAX = 100010; // in int n, q; int root; int shops; int eu[MAX], ev[MAX], ew[MAX]; // i-th edge = (eu[i], ev[i]) vector<pii> edge[MAX]; // to, dis bool isshop[MAX]; // HLD int sz[MAX], par[MAX], dep[MAX], fr[MAX], heavy[MAX], id[MAX], from[MAX], to[MAX]; int ts = 1, ets; // sweep line int dp[MAX]; vector<vi> EV; // modify : time, insert/erase, val // query : time, 2 // sparse table int st[MAX][20]; // res = min(dep[shop] - 2*dep[lca]) + dep[qv] void find_sz(int v, int pv){ // find sz, par, dep, heavy par[v] = pv; sz[v] = 1; from[v] = ets++; int Max = 0; heavy[v] = -1; for(pii e : edge[v]){ int i = e.F, dd = e.S; if(i == pv) continue; dep[i] = dep[v] + dd; find_sz(i, v); sz[v] += sz[i]; if(sz[i] > Max){ Max = sz[i]; heavy[v] = i; } } to[v] = ets++; } void HLD(int v, int pv, int frv){ // HLD subtree v fr[v] = frv; id[v] = ts++; if(heavy[v] != -1) HLD(heavy[v], v, frv); for(pii e : edge[v]){ int i = e.F; if(i == pv or i == heavy[v]) continue; HLD(i, v, i); } } void add_seg(int v){ int val = dep[v]; while(v != root){ // node id : [fr[v], v] // st id : [id[fr[v]], id[v]] EV.pb({id[fr[v]], 1, val}); EV.pb({id[v] + 1, -1, val}); v = par[fr[v]]; } // v == root EV.pb({id[v], 1, val}); EV.pb({id[v] + 1, -1, val}); } inline int query_min(int L, int R){ int rk = __lg(R - L + 1); //int ret = min(st[L][rk], st[R - (1<<rk) + 1][rk]); //cerr<<"query_min("<<L<<", "<<R<<") = "<<ret<<endl; return min(st[L][rk], st[R - (1<<rk) + 1][rk]); } inline int isanc(int u, int v){ return (from[u] <= from[v] and to[v] <= to[u]); } int query_res(int u, int v){ int ret = LNF; while(fr[u] != fr[v]){ ret = min(ret, query_min(id[fr[v]], id[v])); v = par[fr[v]]; } ret = min(ret, query_min(id[u], id[v])); return ret; } signed main(){ ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); // in cin>>n>>shops>>q>>root; FOR(i, 1, n-1, 1){ cin>>eu[i]>>ev[i]>>ew[i]; edge[eu[i]].eb(ev[i], ew[i]); edge[ev[i]].eb(eu[i], ew[i]); } FOR(i, 1, shops, 1){ int C; cin>>C; isshop[C] = 1; } // HLD find_sz(root, root); HLD(root, root, root); /* cerr<<"HLD : "; FOR(i, 1, n, 1){ cerr<<id[i]<<" "; } cerr<<endl; */ // HLD ok // sweep line : // events FOR(i, 1, n, 1){ if(isshop[i]) add_seg(i); EV.pb({i, 2}); } sort(EV.begin(), EV.end()); // min(dep[shop]) multiset<int> owo; for(vi E : EV){ int type = E[1]; if(type < 2){ // modify int val = E[2]; if(type == 1){ // insert owo.insert(val); } else if(type == -1){ // erase owo.erase(owo.find(val)); } } else if(type == 2){ // query int Time = E[0]; if(!owo.empty()) dp[Time] = *owo.begin(); else dp[Time] = LNF; } } // min(dep[shop]) - 2*dep[lca] FOR(i, 1, n, 1){ dp[id[i]] -= 2 * dep[i]; } /* cerr<<"dp : "; FOR(i, 1, n, 1){ if(dp[i] < LNF / 2) cerr<<dp[i]<<" "; else cerr<<"- "; } cerr<<endl; */ // dp ok // sparse table FOR(i, 1, n, 1){ st[i][0] = dp[i]; } FOR(j, 1, 19, 1){ FOR(i, 1, n, 1){ int ii = i + (1<<(j-1)); if(ii <= n) st[i][j] = min(st[i][j-1], st[ii][j-1]); else st[i][j] = st[i][j-1]; } } // query while(q--){ int ie, qv; cin>>ie>>qv; int iu = eu[ie], iv = ev[ie]; if(isanc(iu, qv) and isanc(iv, qv)){ // go to shop if(dep[iu] < dep[iv]) swap(iu, iv); // can only move in subtree iu // query : node iu ~ node qv // res = min(dep[shop] - 2*dep[lca]) + dep[qv] int res = query_res(iu, qv) + dep[qv]; if(res > LNF / 2) cout<<"oo"<<'\n'; else cout<<res<<'\n'; } else{ // escaped cout<<"escaped"<<'\n'; } } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...