Submission #924718

#TimeUsernameProblemLanguageResultExecution timeMemory
924718KarootValley (BOI19_valley)C++17
100 / 100
322 ms80192 KiB
#include <iostream> #include <cmath> #include <unordered_map> #include <map> #include <set> #include <queue> #include <vector> #include <string> #include <iomanip> #include <algorithm> #define all(x) (x).begin(), (x).end() #define rall(x) (x).rbegin(), (x).rend() using namespace std; typedef long long ll; ll linf = 1e15+1; inline void scoobydoobydoo(){ ios::sync_with_stdio(false); ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); } const int MAXN = 1e5+1; vector<pair<ll, ll>> adj[MAXN]; ll parent[MAXN], parentW[MAXN]; vector<ll> children[MAXN]; ll depth[MAXN], subSz[MAXN]; pair<ll, ll> eulerTour[MAXN]; ll eulerCounter = 0; ll closestStore[MAXN]; bool isStore[MAXN]; ll rootTree(ll node, ll pare, ll w, ll vikt){ depth[node] = w; eulerTour[node].first = eulerCounter++; parent[node] = pare; parentW[node] = vikt; subSz[node] = 1; ll mini = 1e18; for (auto p : adj[node]){ if (p.first == pare)continue; subSz[node] += rootTree(p.first, node, w+1, p.second); mini = min(mini, closestStore[p.first]+p.second); children[node].push_back(p.first); } closestStore[node] = (isStore[node] ? 0 : mini); eulerTour[node].second = eulerCounter++; return subSz[node]; } struct Node { ll lc, rc; ll leftOf, rightOf; ll mini, sum; Node(){ lc = -1; rc = -1; mini = 10000000; sum = 0; leftOf = -1; rightOf = -1; } }; struct Chain { ll tN; ll lN; ll root; }; Node ST[8*MAXN]; ll counter = 0; ll chainC = 0; ll nodeToChain[MAXN]; Chain chains[MAXN]; ll vals[MAXN]; ll pW[MAXN]; bool comp(const ll& i1, const ll& i2){ return subSz[i1] < subSz[i2]; } void heavydfs(ll node){ nodeToChain[node] = chainC; sort(rall(children[node]), comp); if (children[node].empty()){ chains[chainC].lN = node; return; } heavydfs(children[node][0]); for (ll i = 1; i < children[node].size(); i++){ chainC++; chains[chainC].tN = children[node][i]; heavydfs(children[node][i]); } return; } void buildTree(ll l, ll r, ll node){ ST[node].leftOf = l; ST[node].rightOf = r; if (l == r){ ST[node].mini = vals[l]; ST[node].sum = pW[l]; return; } ll mid = (l+r)>>1; ST[node].lc = counter++; buildTree(l, mid, ST[node].lc); ST[node].rc = counter++; buildTree(mid+1, r, ST[node].rc); ST[node].mini = min(ST[ST[node].lc].mini+ST[ST[node].rc].sum, ST[ST[node].rc].mini); ST[node].sum = ST[ST[node].lc].sum+ST[ST[node].rc].sum; return; } void buildSegments(){ for (ll i = 0; i <= chainC; i++){ ll howMany = depth[chains[i].lN]-depth[chains[i].tN]; ll current = chains[i].lN; for (ll j = howMany; j >= 0; j--){ vals[j] = closestStore[current]; pW[j] = parentW[current]; current = parent[current]; } chains[i].root = counter++; buildTree(0, howMany, chains[i].root); } } vector<Node> findMother(ll l, ll r, ll node){ if (l == ST[node].leftOf && r == ST[node].rightOf){ return {ST[node]}; } ll a = ST[node].lc, b = ST[node].rc; if (ST[a].rightOf >= r)return findMother(l, r, a); if (ST[b].leftOf <= l)return findMother(l, r, b); vector<Node> ret = findMother(l, ST[a].rightOf, a); vector<Node> r1 = findMother(ST[b].leftOf, r, b); for (Node N : r1)ret.push_back(N); return ret; } //summa, mini pair<ll, ll> query(ll starting, ll ending, ll chainID, ll startSu){ ll topp = chains[chainID].tN; ll l = depth[ending]-depth[topp]; ll r = depth[starting]-depth[topp]; //cout << chainID << "; " << l << " . " << r << endl; //cout << l << "_" << r << "_" << starting << "_" << ending << "_" << chainID << "_" << startSu << endl; vector<Node> motherNodes = findMother(l, r, chains[chainID].root); reverse(all(motherNodes)); ll su = startSu; ll mini = 1e18; for (Node N : motherNodes){ mini = min(mini, N.mini+su); su += N.sum; } return make_pair(su, mini); } ll indexToNode[MAXN]; int main(){ scoobydoobydoo(); //freopen("valley.in", "r", stdin); //freopen("valley.ans", "w", stdout); ll n, s, q, e; cin >> n >> s >> q >> e; vector<vector<ll> > edges; for (ll i = 0; i < n-1; i++){ ll a, b, w; cin >> a >> b >> w; a--; b--; adj[a].push_back({b, w}); adj[b].push_back({a, w}); edges.push_back({a, b, w}); } e--; for (ll i = 0; i < s; i++){ ll a; cin >> a; a--; isStore[a] = true; } rootTree(e, e, 0, 0); //cout << "here" << endl; ll il = 0; for (auto v : edges){ ll a = v[0]; ll b = v[1]; if (depth[a] < depth[b]) indexToNode[il] = b; else indexToNode[il] = a; il++; } vector<ll> ans; /*cout << "closestStore: " << endl; for (int i = 0; i < n; i++){ cout << i << ": " << closestStore[i] << endl; }*/ chains[0].tN = e; heavydfs(e); buildSegments(); /*cout << "CHAINS:" << endl; for (int i = 0; i <= chainC; i++){ Chain C = chains[i]; cout << C.lN << " " << C.tN << " " << C.root << endl; }*/ while (q--){ ll I, R; cin >> I >> R; I--; R--; I = indexToNode[I]; //cout << I << "; " << R << endl; if (eulerTour[I].first > eulerTour[R].first || eulerTour[I].second < eulerTour[R].second){ ans.push_back(-2); continue; } if (closestStore[I] > 1e17){ ans.push_back(-1); continue; } ll sum = 0; ll best = 1e18; ll current = nodeToChain[R]; ll node = R; while (current != nodeToChain[I]){ pair<ll, ll> p = query(node, chains[current].tN, current, sum); sum = p.first; //if (chains[current].tN != chains[current].lN)sum += parentW[chains[current].tN]; //sum += parentW[chains[current].tN]; best = min(best, p.second); node = parent[chains[current].tN]; //cout << p.first << " + " << p.second << endl; current = nodeToChain[node]; } pair<ll, ll> p = query(node, I, current, sum); //cout << p.first << " + " << p.second << endl; best = min(best, p.second); ans.push_back(best); } for (ll x : ans){ if (x == -1)cout << "oo" << endl; else if (x == -2)cout << "escaped" << endl; else cout << x << endl; } return 0; }

Compilation message (stderr)

valley.cpp: In function 'void heavydfs(ll)':
valley.cpp:100:26: warning: comparison of integer expressions of different signedness: 'll' {aka 'long long int'} and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  100 |         for (ll i = 1; i < children[node].size(); i++){
      |                        ~~^~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...