Submission #1367677

#TimeUsernameProblemLanguageResultExecution timeMemory
1367677vuvietTwo Currencies (JOI23_currencies)C++20
100 / 100
783 ms27500 KiB
/**
 *     Author:       trviet
 *     Studies at:   Le Hong Phong High School for the Gifted
**/

#include <bits/stdc++.h>

#define ____vuviet__ signed main
#define taskname "trvietbels"

using namespace std;
using metal = pair<long long, long long>;

#define gold first
#define silver second

constexpr int maxn = 1e5 + 5;
int n, m, q, timer = 0, lo[maxn], hi[maxn];
int par[maxn], head[maxn], id[2][maxn], sz[maxn];

long long total_gold[maxn], res[maxn];
metal bit[maxn];
// id(0) = edge -> v, id(1) = hld id

metal operator + (metal a, metal b)
{
    metal res;
    res.gold = a.gold + b.gold;
    res.silver = a.silver + b.silver;
    return res;
}

metal operator - (metal a, metal b)
{
    metal res;
    res.gold = a.gold - b.gold;
    res.silver = a.silver - b.silver;
    return res;
}

void update(int i, long long x, long long y)
{
    metal New = {x, y};
    for (; i <= n; i += i & -i)
        bit[i] = bit[i] + New;
}

metal get(int i)
{
    metal res = {0, 0};
    for (; i > 0; i -= i & -i)
        res = res + bit[i];
    return res;
}

metal cost(int l, int r)
{
    return get(r) - get(l - 1);
}

metal query(int u, int v)
{
    metal res = {0, 0};
    while (head[u] != head[v])
    {
        if (sz[head[u]] > sz[head[v]]) swap(u, v);
        res = res + cost(id[1][head[u]], id[1][u]);
        u = par[head[u]];
    }
    if (sz[u] > sz[v]) swap(u, v);
    res = res + cost(id[1][v] + 1, id[1][u]);
    return res;
}

struct Checkpoint
{
    int u;
    long long c;
    bool operator < (Checkpoint o) const {
        return c < o.c;
    }
} pts[maxn];

struct Edge
{
    int vertex, id;
};

struct Query
{
    int s, t, x;
    long long y;
} qr[maxn];

vector<Edge> tree[maxn];

void DFSVisit(int u, int p)
{
    par[u] = p, sz[u] = 1;
    for (Edge child : tree[u])
    {
        int v = child.vertex, i = child.id;
        if (v != p) {
            DFSVisit(v, u), sz[u] += sz[v], id[0][i] = v;
        }
    }
}

void Heavy(int u, int h, int p)
{
    head[u] = h, id[1][u] = ++timer;
    if (tree[u].empty()) return;
    int x = -1;
    for (Edge child : tree[u])
    {
        int v = child.vertex;
        if (v != p && (x == -1 || sz[v] > sz[x]))
            x = v;
    }
    if (x != -1) Heavy(x, h, u);
    for (Edge child : tree[u])
    {
        int v = child.vertex;
        if (v != p && v != x)
            Heavy(v, v, u);
    }
}

void solvebytrvietbels()
{
    cin >> n >> m >> q;
    for (int i = 2; i <= n; ++i)
    {
        int u, v;
        cin >> u >> v;
        tree[u].push_back({v, i - 1});
        tree[v].push_back({u, i - 1});
    }
    DFSVisit(1, 0);
    Heavy(1, 1, 0);
    for (int i = 1; i <= m; ++i)
    {
        int p;
        long long c;
        cin >> p >> c;
        pts[i] = {id[0][p], c};
    }
    sort(pts + 1, pts + 1 + m);
    for (int i = 1; i <= m; ++i)
        update(id[1][pts[i].u], 1, 0);

    for (int i = 1; i <= q; ++i)
    {
        int s, t, x;
        long long y;
        cin >> s >> t >> x >> y;
        qr[i] = {s, t, x, y};
        total_gold[i] = query(s, t).gold;
        lo[i] = 1, hi[i] = m;
    }

    int Log2 = __lg(m + 5);
    for (int t = 0; t < Log2 + 1; ++t)
    {
        for (int i = 1; i <= n; ++i)
            bit[i] = {0, 0};

        vector<vector<int>> queries(m + 5);
        for (int i = 1; i <= q; ++i)
            if (lo[i] <= hi[i])
                queries[(lo[i] + hi[i]) / 2].push_back(i);

        for (int i = 1; i <= m; ++i)
        {
            update(id[1][pts[i].u], 1, pts[i].c);
            for (int id : queries[i])
            {
                metal cur = query(qr[id].s, qr[id].t);
                if (cur.silver <= qr[id].y) {
                    res[id] = cur.first, lo[id] = i + 1;
                } else {
                    hi[id] = i - 1;
                }
            }
        }
    }
    for (int i = 1; i <= q; ++i)
    {
        long long need = total_gold[i] - res[i];
        cout << (need > qr[i].x ? -1 : qr[i].x - need) << "\n";
    }
}

void freopen_stdio(string speech)
{
    cin.tie(0)->sync_with_stdio(0);
    cerr << speech << "\n";
    if (fopen(taskname ".inp", "r"))
    {
        freopen(taskname ".inp", "r", stdin);
        freopen(taskname ".out", "w", stdout);
    }
}

____vuviet__()
{
    freopen_stdio("...miss you...");
    int t = 1;
    // cin >> t;
    while (t-- > 0)
        solvebytrvietbels();
    return 0;
}

Compilation message (stderr)

currencies.cpp: In function 'void freopen_stdio(std::string)':
currencies.cpp:200:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  200 |         freopen(taskname ".inp", "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
currencies.cpp:201:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  201 |         freopen(taskname ".out", "w", stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...