Submission #915217

#TimeUsernameProblemLanguageResultExecution timeMemory
915217berrTwo Currencies (JOI23_currencies)C++17
100 / 100
1868 ms149724 KiB
#include <bits/stdc++.h>
using namespace std;

#define int long long
const int mod = 1e9+7;

struct segtree{
    using T = array<int, 2>;
    vector<T> st;
    vector<int> ar;
    int n, tl, tr;

    T base = {0, 0};

    segtree(){
        st.resize(1);
    };

    T merge(T x, T y){
        x[0] += y[0]; x[1] += y[1];
        return x;
    }

    segtree(vector<int> a){
        ar = a;
        n = a.size();

        st.resize(n*4, base);

        build(1, 0, n-1);
    }

    void build(int v, int l, int r){
        if(l==r){
            st[v] = {0, ar[l]};
        }
        else if(l < r){
            int mid = (l + r) / 2;

            build(v*2, l, mid);
            build(v*2+1, mid+1, r);

            st[v] = merge(st[v*2], st[v*2+1]);  
        }
    }

    void upd(int v, int l, int r, int pos, T x){
        if(l==r){
            st[v] = merge(st[v], x);
        }
        else if(l<r){
            int mid = (l+r) / 2;

            if (pos <= mid)upd(v*2, l, mid, pos, x);
            else upd(v*2+1, mid+1, r, pos, x);

            st[v] = merge(st[v*2], st[v*2+1]);
        }

    }
    void upd(int v, T gh){
        upd(1, 0, n-1, v, gh);
    }

    T get(int v, int l, int r){
        if(r<tl || l > tr) return base;
        else if(l>=tl && r<= tr){
            return st[v];
        } 
        else{
            int mid = (l+r) / 2;

            return merge(get(v*2, l, mid), get(v*2+1, mid+1, r));
        }
    }

    T operator()(int l, int r){
        tl = l; tr = r;
        if(l>r) return {0, 0};

        return get(1, 0, n-1);
    }

};
vector<segtree> st;

struct hld{

    vector<vector<array<int, 2>>> g;
    vector<vector<int>> chain;
    vector<int> s, c, d, p_node, p_edge, val;
    vector<int> pos_edge, ind_edge;
    vector<int> pos_node, ind_node;
    int n;
    
    hld(){};

    hld(int _n, vector<vector<array<int, 2>>>a, vector<int> v){
        n = _n; g = a;
        s.resize(n, 1); d.resize(n);
        pos_edge.resize(n); ind_edge.resize(n);
        pos_node.resize(n); ind_node.resize(n);

        p_edge.resize(n);  
        p_node.resize(n);

        val = v;
        d[0] = -1;
        dfs(0, 0); dfs2(0, 0);
        p_edge[0] = n-1;
        for(int i=0; i<chain.size(); i++){
            reverse(chain[i].begin(), chain[i].end());

            vector<int> x;
            for(int l=0; l<chain[i].size(); l++){
                int node = chain[i][l];
                int edge  = p_edge[node];

                ind_edge[edge] = ind_node[node] = l;
                pos_edge[edge] = pos_node[node] = i;


                x.push_back(val[edge]);
            }

            st.push_back(segtree(x));
        }
    };

    void dfs(int v, int par){
        p_node[v] = par;

        for(int i = 0; i <g[v].size(); i++){
            auto [x, y] = g[v][i];
            
            if(x!=par){
                dfs(x, v);
                p_edge[x] = y;
                s[v] += s[x];
                if(s[x] > s[g[v][0][0]]||g[v][0][0]==par){
                    swap(g[v][0], g[v][i]);
                }
            }
        }

    }

    void dfs2(int v, int p){
        c.push_back(v);

        d[v] = d[p]+1;
        for(auto &[x, y]: g[v]){
            if(x==p) continue;
            dfs2(x, v);
        }

        if(g[v].size()==1 && v!=p && c.size()){
            chain.push_back(c);
            c.clear();
        }
    }


    array<int, 2> merge(array<int, 2> x, array<int, 2> y){
        x[0] += y[0]; x[1] += y[1];
        return x;
    }
    array<int, 2> get(int v, int u){

        int pv = pos_node[v], pu = pos_node[u];
        array<int, 2> gh ={0, 0};

        while(pv != pu){

            if(d[chain[pu].back()] > d[chain[pv].back()]){
                swap(pv, pu);
                swap(u, v);
            }

            gh=merge(gh, st[pv](ind_node[v], ind_node[chain[pv].back()]));
            v = p_node[chain[pv].back()];
            pv = pos_node[v];
        }

        if(d[v] <d[u]) swap(u, v);

        gh = merge(gh, st[pv](ind_node[v], ind_node[u]-1));

        return gh;
    }

};


hld h;

struct comparer{
    int k = 0;
    int n;
    vector<array<int, 2>> val;
    vector<int> ind;
  
    comparer(vector<array<int, 2>> v){
        n = v.size();
        val = v;
        k = 0;

        ind.resize(n);

        iota(ind.begin(), ind.end(), 0);
        sort(ind.begin(), ind.end(), [&](int x, int y){
            return val[x][1] > val[y][1];
        });


    };

    void operator++(){
        int pf = val[ind[k]][0];
        int pos= h.pos_edge[pf];
        int id = h.ind_edge[pf];
        auto x = st[pos](id, id);

        st[pos].upd(id, {1, -val[ind[k]][1]});
         x = st[pos](id, id);

        k++;
    }
    void operator--(){
        k--;

        int pf = val[ind[k]][0];
        int pos= h.pos_edge[pf];
        int id = h.ind_edge[pf];

        st[pos].upd(id, {-1, val[ind[k]][1]});
    }

};

struct query{
    int u=0, v=0;
    int x=0, y=0; 
    int ind=0;

    query(){};

    query(array<int, 5> s){
        u=s[0]; v = s[1]; x=s[2]; y=s[3];
        ind = s[4];
    }
    bool check(){

        auto a = h.get(u, v);
        return (a[0]<x && a[1]>y); 
    }

    int check2(){
        auto a = h.get(u, v);

        if(a[0]<=x && a[1]<=y){
            return x-a[0];
        }
        return -1;
    }
};

signed main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    
    int n, m, q; cin >> n >> m >> q;
    n++;
    vector<int> val(n);
    vector<array<int, 2>> val2(m);
    vector<vector<array<int, 2>>> g(n);
    vector<array<int, 2>> e(n-2);
    
    for (auto &[x, y]: e){
        cin >> x >> y;
        x--; y--;
    }


    e.push_back({0, n-1});

    for(int i=0; i<m; i++){
        int z, c; cin >> z >> c;
        val[z-1] += c;    
        val2[i]={z-1, c};     
    }   

    for(int i=0; i<n; i++){
        if(val[i]==0) val2.push_back({i, 0});
    }

    for(int i=0; i<n-1; i++){
        auto [x, y]=e[i];
        g[x].push_back({y, i});
        g[y].push_back({x, i});
    }

    h = hld(n, g, val);
    comparer cmp(val2);

    vector<query> qu(q);

    for(int i=0; i<q; i++){
        array<int, 5> f;
        for(int l=0; l<4; l++) cin >> f[l];

        f[0]--; f[1]--;
        f[4] = i;
        qu[i] = query(f);


    }   

    vector<int> ans(q);

    auto rec = [&](vector<query> x, int l, int r,auto &&rec)->void{
      //  cout<<l<<" "<<r<<"\n";
        if(l==r){

            while(cmp.k<l){
                ++cmp;
            }

            while(cmp.k>l){
                --cmp;
            }

            for(auto i: x){
           //     cout<<i.ind<<" "<<cmp.k<<"a\n";
                ans[i.ind] = i.check2();
            }
        }
        else if(l<r){
            vector<query> a, b;
            int mid = (l+r)/2;
           while(cmp.k < mid){
                ++cmp;
            }

            while(cmp.k > mid){
                --cmp;
            }
            //cout<<l<<" "<<r<<"\n";
            for(auto i: x){
                if(i.check()) a.push_back(i);
                else b.push_back(i);
            }

            if(a.size())
                rec(a, mid+1, r, rec);
            if(b.size())
                rec(b, l, mid, rec);

        }

    };

    rec(qu, 0, val2.size()-1, rec);
    for(auto i: ans) cout<<i<<"\n";
}

Compilation message (stderr)

currencies.cpp: In constructor 'hld::hld(long long int, std::vector<std::vector<std::array<long long int, 2> > >, std::vector<long long int>)':
currencies.cpp:111:23: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<std::vector<long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  111 |         for(int i=0; i<chain.size(); i++){
      |                      ~^~~~~~~~~~~~~
currencies.cpp:115:27: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  115 |             for(int l=0; l<chain[i].size(); l++){
      |                          ~^~~~~~~~~~~~~~~~
currencies.cpp: In member function 'void hld::dfs(long long int, long long int)':
currencies.cpp:133:26: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<std::array<long long int, 2> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  133 |         for(int i = 0; i <g[v].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...