Submission #924718

# Submission time Handle Problem Language Result Execution time Memory
924718 2024-02-09T14:41:11 Z Karoot Valley (BOI19_valley) C++17
100 / 100
322 ms 80192 KB
    #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

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 time Memory Grader output
1 Correct 27 ms 51800 KB Output is correct
2 Correct 21 ms 51780 KB Output is correct
3 Correct 21 ms 51884 KB Output is correct
4 Correct 21 ms 51928 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 27 ms 51800 KB Output is correct
2 Correct 21 ms 51780 KB Output is correct
3 Correct 21 ms 51884 KB Output is correct
4 Correct 21 ms 51928 KB Output is correct
5 Correct 10 ms 51548 KB Output is correct
6 Correct 10 ms 51548 KB Output is correct
7 Correct 10 ms 51740 KB Output is correct
8 Correct 10 ms 51548 KB Output is correct
9 Correct 10 ms 51548 KB Output is correct
10 Correct 11 ms 51548 KB Output is correct
11 Correct 10 ms 51704 KB Output is correct
12 Correct 10 ms 51544 KB Output is correct
13 Correct 10 ms 51804 KB Output is correct
14 Correct 10 ms 51548 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 231 ms 72028 KB Output is correct
2 Correct 225 ms 72440 KB Output is correct
3 Correct 247 ms 73196 KB Output is correct
4 Correct 259 ms 75468 KB Output is correct
5 Correct 254 ms 75512 KB Output is correct
6 Correct 322 ms 79884 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 27 ms 51800 KB Output is correct
2 Correct 21 ms 51780 KB Output is correct
3 Correct 21 ms 51884 KB Output is correct
4 Correct 21 ms 51928 KB Output is correct
5 Correct 10 ms 51548 KB Output is correct
6 Correct 10 ms 51548 KB Output is correct
7 Correct 10 ms 51740 KB Output is correct
8 Correct 10 ms 51548 KB Output is correct
9 Correct 10 ms 51548 KB Output is correct
10 Correct 11 ms 51548 KB Output is correct
11 Correct 10 ms 51704 KB Output is correct
12 Correct 10 ms 51544 KB Output is correct
13 Correct 10 ms 51804 KB Output is correct
14 Correct 10 ms 51548 KB Output is correct
15 Correct 231 ms 72028 KB Output is correct
16 Correct 225 ms 72440 KB Output is correct
17 Correct 247 ms 73196 KB Output is correct
18 Correct 259 ms 75468 KB Output is correct
19 Correct 254 ms 75512 KB Output is correct
20 Correct 322 ms 79884 KB Output is correct
21 Correct 211 ms 71804 KB Output is correct
22 Correct 231 ms 71804 KB Output is correct
23 Correct 207 ms 72096 KB Output is correct
24 Correct 249 ms 75452 KB Output is correct
25 Correct 273 ms 80192 KB Output is correct
26 Correct 221 ms 71480 KB Output is correct
27 Correct 207 ms 72604 KB Output is correct
28 Correct 210 ms 72188 KB Output is correct
29 Correct 259 ms 74640 KB Output is correct
30 Correct 273 ms 76792 KB Output is correct
31 Correct 196 ms 71416 KB Output is correct
32 Correct 222 ms 71764 KB Output is correct
33 Correct 221 ms 72188 KB Output is correct
34 Correct 246 ms 75196 KB Output is correct
35 Correct 254 ms 80184 KB Output is correct
36 Correct 262 ms 74924 KB Output is correct