Submission #893214

#TimeUsernameProblemLanguageResultExecution timeMemory
893214VerdantGMDTwo Currencies (JOI23_currencies)C++17
100 / 100
1117 ms56788 KiB
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
int n, m, q;
vector<pair<int, int> > tab[100005];
vector<pair<int, int> > adds;
vector<int> mids[100005];
struct query
{
    int l;
    int r;
    int mid;
    int lca;
    int a;
    int b;
    int gold;
    int wyn;
    long long silver;
    int coinsatloss = 0;
};

vector<query> queries;
int jp[100005][21];
int checked[100006];
int timee = 1;
int preorder[100005];
int postorder[100005];
pair<long long, int> tree[500005];
int base;
int vfe[100005];

void dfs(int p, int parent)
{
    preorder[p] = timee;
    timee++;
    for(int i = 0; i < tab[p].size(); i++)
    {
        if(tab[p][i].first != parent)
        {
            vfe[tab[p][i].second] = tab[p][i].first;
            checked[tab[p][i].first] = checked[p] + 1;

            jp[tab[p][i].first][0] = p;
            for(int o = 1; (1 << o) <= checked[tab[p][i].first]; o++)
            {
                jp[tab[p][i].first][o] = jp[ jp[tab[p][i].first] [o-1] ][o - 1];
            }

            dfs(tab[p][i].first, p);
        }
    }
    postorder[p] = timee;
    timee++;
}

void upd(int a, int val, int add)
{
    a += base;
    tree[a].first += val;
    tree[a].second += add;
    a/=2;
    while(a != 0)
    {
        tree[a].first = tree[a*2].first + tree[a*2+1].first;
        tree[a].second = tree[a*2].second + tree[a*2+1].second;
        a/=2;
    }
}

long long treequery(int a, int b)
{
    a += base - 1;
    b += base + 1;
    long long res = 0 ;
    while(a/2 != b/2)
    {
        if(a % 2 == 0)
        {
            res += tree[a+1].first;
        }
        if(b % 2 == 1)
        {
            res += tree[b-1].first;
        }
        a/=2;
        b/=2;
    }
    return res;
}

int treequeryamount(int a, int b)
{
    a += base - 1;
    b += base + 1;
    int res = 0 ;
    while(a/2 != b/2)
    {
        if(a % 2 == 0)
        {
            res += tree[a+1].second;
        }
        if(b % 2 == 1)
        {
            res += tree[b-1].second;
        }
        a/=2;
        b/=2;
    }
    return res;
}

int LCA(int a, int b)
{
    if(checked[b] > checked[a])
    {
        swap(a, b);
    }
    for(int i = 20; i >= 0; i--)
    {
        if(checked[a] - checked[b] >= (1 << i))
        {
            a = jp[a][i];
        }
    }
    if(a == b)
    {
        return a;
    }
    for(int i = 20; i >= 0; i--)
    {
        if(jp[a][i] != jp[b][i])
        {
            a = jp[a][i];
            b = jp[b][i];
        }
    }
    return jp[a][0];
}

void superbinsearch()
{
    int leftt = q;
    while (leftt > 0)
    {
        for(int i = 0; i < m; i++)
        {
            upd(preorder[vfe[adds[i].second]], adds[i].first, 1);
            upd(postorder[vfe[adds[i].second]], -adds[i].first, -1);

            for(int qnum : mids[i])
            {
                long long wyn = 0;
                int a = queries[qnum].a;
                int b = queries[qnum].b;
                if(checked[a] < checked[b])
                {
                    swap(a, b);
                }
                wyn += treequery(preorder[queries[qnum].lca], preorder[a]);
                wyn -= tree[preorder[queries[qnum].lca] + base].first;
                if(b != queries[qnum].lca)
                {
                    wyn += treequery(preorder[queries[qnum].lca], preorder[b]);
                    wyn -= tree[preorder[queries[qnum].lca] + base].first;
                }
                //cout << "mid" << i << " qnum" << qnum << " wyn" << wyn << endl;

                if(wyn > queries[qnum].silver)
                {
                    queries[qnum].r = queries[qnum].mid - 1;
                }
                else
                {
                    queries[qnum].l = queries[qnum].mid + 1;
                }

                if(queries[qnum].r < queries[qnum].l)
                {
                    leftt--;
                    queries[qnum].wyn = queries[qnum].r;
                }
                else
                {
                    queries[qnum].mid = (queries[qnum].l + queries[qnum].r)/2;
                    mids[queries[qnum].mid].push_back(qnum);
                }
            }
            mids[i].clear();
        }
        for(int i = 0; i < 2*n + base + 1000; i++)
        {
            tree[i].first = 0;
            tree[i].second = 0;
        }
    }
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> m >> q;
    base = 2 * n;
    for(int i = 1; i <= n-1; i++)
    {
        int a, b;
        cin >> a >> b;
        tab[a].push_back({b, i});
        tab[b].push_back({a, i});
    }
    dfs(1, 1);

    for(int i = 0; i < m; i++)
    {
        int a, b;
        cin >> a >> b;
        adds.push_back({b, a});
    }


    for(int i = 0; i < q; i++)
    {
        int a, b, c;
        long long d;
        cin >> a >> b >> c >> d;
        query que;
        que.a = a;
        que.b = b;
        que.gold = c;
        que.silver = d;
        que.l = 0;
        que.r = m-1;
        que.mid = (m-1)/2;
        que.lca = LCA(a, b);
        mids[que.mid].push_back(i);
        queries.push_back(que);
    }
    sort(adds.begin(), adds.end());
    superbinsearch();

    for(int i = 0; i < q; i++)
    {
        mids[queries[i].wyn].push_back(i);
    }

    for(int i = 0; i < m; i++)
    {
        upd(preorder[vfe[adds[i].second]], adds[i].first, 1);
        upd(postorder[vfe[adds[i].second]], -adds[i].first, -1);

        for(int qnum : mids[i])
        {
            int wyn = 0;
            int a = queries[qnum].a;
            int b = queries[qnum].b;
            if(checked[a] < checked[b])
            {
                swap(a, b);
            }
            wyn += treequeryamount(preorder[queries[qnum].lca], preorder[a]);
            wyn -= tree[preorder[queries[qnum].lca] + base].second;
            if(b != queries[qnum].lca)
            {
                wyn += treequeryamount(preorder[queries[qnum].lca], preorder[b]);
                wyn -= tree[preorder[queries[qnum].lca] + base].second;
            }
            queries[qnum].coinsatloss = wyn;
        }
        mids[i].clear();
    }

    for(int i = 0; i < q; i++)
    {
        int wyn = 0;
        int a = queries[i].a;
        int b = queries[i].b;
        if(checked[a] < checked[b])
        {
            swap(a, b);
        }
        wyn += treequeryamount(preorder[queries[i].lca], preorder[a]);
        wyn -= tree[preorder[queries[i].lca] + base].second;
        if(b != queries[i].lca)
        {
            wyn += treequeryamount(preorder[queries[i].lca], preorder[b]);
            wyn -= tree[preorder[queries[i].lca] + base].second;
        }
       // cout << "wyn " << wyn << " buyable " << queries[i].coinsatloss << endl;
        
        cout << max(-1, queries[i].gold - wyn + queries[i].coinsatloss) << endl;
    }

}

Compilation message (stderr)

currencies.cpp: In function 'void dfs(int, int)':
currencies.cpp:36:22: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   36 |     for(int i = 0; i < tab[p].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...