Submission #1295892

#TimeUsernameProblemLanguageResultExecution timeMemory
1295892ducanh0811Traffickers (RMI18_traffickers)C++20
0 / 100
302 ms589824 KiB
#include <bits/stdc++.h>
#define int                 long long
#define FOR(i, a, b)        for (int i = (a), _b = (b); i <= _b; ++i)
using namespace std;

#define MAXN 30005
int n, k, q;
vector<int> g[MAXN];

struct node {
    int sum;
    int lz;
    node(int _sum = 0, int _lz = 0) {
        sum = _sum;
        lz = _lz;
    }
};

node combine(const node &a, const node &b) {
    node res = node();
    res.sum = a.sum + b.sum;
    return res;
}

struct SMT {
    int n;
    vector<node> st;
    SMT(int _n = 0) {
        n = _n;
        st.assign((n << 2) + 5, node());
    }

    void pushDown(int id, int l, int r, int mid) {
        if (st[id].lz == 0) return;
        st[id << 1].sum += st[id].lz * (mid - l + 1);
        st[id << 1].lz  += st[id].lz;
        st[id << 1 | 1].sum += st[id].lz * (r - mid);
        st[id << 1 | 1].lz  += st[id].lz;
        st[id].lz = 0;
    }

    void upd(int id, int l, int r, int u, int v, int val) {
        if (v < l || r < u) return;
        if (u <= l && r <= v) {
            st[id].sum += val * (r - l + 1);
            st[id].lz += val;
            return;
        }
        int mid = (l + r) >> 1;
        pushDown(id, l, r, mid);
        upd(id << 1, l, mid, u, v, val);
        upd(id << 1 | 1, mid + 1, r, u, v, val);
        st[id] = combine(st[id << 1], st[id << 1 | 1]);
    }
    void upd(int u, int v, int val) {
        upd(1, 1, n, u, v, val);
    }

    node get(int id, int l, int r, int u, int v) {
        if (v < l || r < u) return node();
        if (u <= l && r <= v) return st[id];
        int mid = (l + r) >> 1;
        pushDown(id, l, r, mid);
        return combine(get(id << 1, l, mid, u, v), get(id << 1 | 1, mid + 1, r, u, v));
    }
    int get(int u, int v) {
        return get(1, 1, n, u, v).sum;
    }
} tree[22][22];

int child[MAXN], par[MAXN], heavy[MAXN], dep[MAXN];
int pos[MAXN], head[MAXN], timer = 0;

void dfs(int u, int p) {
    child[u] = 1;
    int mx_c = 0;
    for (int &v : g[u]) {
        if (v == p) continue;
        dep[v] = dep[u] + 1;
        par[v] = u;
        dfs(v, u);
        child[u] += child[v];
        if (child[v] > mx_c) {
            mx_c = child[v];
            heavy[u] = v;
        }
    }
}

void hld(int u, int h) {
    head[u] = h;
    pos[u] = ++timer;
    if (heavy[u] != 0) hld(heavy[u], h);
    for (int &v : g[u]) {
        if (v == par[u] || v == heavy[u]) continue;
        hld(v, v);
    }
}

int LCA(int u, int v) {
    while (head[u] != head[v]) {
        if (dep[head[u]] < dep[head[v]]) swap(u, v);
        u = par[head[u]];
    }
    if (dep[u] > dep[v]) swap(u, v);
    return u;
}

void upd(int u, int v, int val, int id, int length) {
    while (head[u] != head[v]) {
        if (dep[head[u]] < dep[head[v]]) swap(u, v);
        tree[length][id].upd(pos[head[u]], pos[u], val);
        u = par[head[u]];
    }
    if (pos[u] > pos[v]) swap(u, v);
    tree[length][id].upd(pos[u], pos[v], val);
}

int query(int u, int v, int id, int length) {
    int res = 0;
    while (head[u] != head[v]) {
        if (dep[head[u]] < dep[head[v]]) swap(u, v);
        res += tree[length][id].get(pos[head[u]], pos[u]);
        u = par[head[u]];
    }
    if (pos[u] > pos[v]) swap(u, v);
    res += tree[length][id].get(pos[u], pos[v]);
    return res;
}

void modifyPath(int sta, int fin, int delta) {
    int mid = LCA(sta, fin);
    int numNode = dep[sta] + dep[fin] - 2 * dep[mid] + 1;
    vector<int> up, down;
    while (sta != mid) {
        up.push_back(sta);
        sta = par[sta];
    }
    while (fin != mid) {
        down.push_back(fin);
        fin = par[fin];
    }
    reverse(down.begin(), down.end());
    vector<int> nodes;
    nodes.insert(nodes.end(), up.begin(), up.end());
    nodes.push_back(mid);
    nodes.insert(nodes.end(), down.begin(), down.end());
    FOR(i, 0, nodes.size() - 1) {
        upd(nodes[0], nodes[i], delta, i, numNode);
    }
}

int cost(int t1, int t2, int numNode, int a, int b) {
    int res = query(a, b, t1 % numNode, numNode);
//    cout << "ko: " << numNode << " " << res << '\n';
    int t = t2 - t1;
    int fullCount = t / numNode;
    res += query(a, b, numNode - 1, numNode) * fullCount;
    t1 %= numNode;
    t2 %= numNode;
//    cout << "ok: " << numNode << " " << res << '\n';
    if (t1 <= t2) {
        res += query(a, b, t2, numNode);
        res -= query(a, b, t1, numNode);
    } else {
        res += query(a, b, numNode - 1, numNode);
        res -= query(a, b, t1, numNode);
        res += query(a, b, t2, numNode);
    }
    return res;
}

void solve() {
    cin >> n;
    FOR(i, 1, n - 1) {
        int u, v; cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    FOR(i, 0, 20) FOR(j, 0, 20) tree[i][j] = SMT(n);
    dfs(1, 0);
    hld(1, 1);
    cin >> k;
    FOR(i, 1, k) {
        int x, y; cin >> x >> y;
        modifyPath(x, y, 1);
    }
    cin >> q;
    FOR(i, 1, q) {
        int type, a, b;
        cin >> type >> a >> b;
        if (type == 1) modifyPath(a, b, 1);
        else if (type == 2) modifyPath(a, b, -1);
        else if (type == 3) {
            int t1, t2; cin >> t1 >> t2;
            int res = 0;
            FOR(numNode, 1, 20) {
                res += cost(t1, t2, numNode, a, b);
            }
            cout << res << '\n';
        }
    }
}

#define task "test"
int32_t main() {
    if (fopen(task".inp","r")) {
        freopen(task".inp","r",stdin);
        freopen(task".out","w",stdout);
    }
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    solve();
    return 0;
}

Compilation message (stderr)

traffickers.cpp: In function 'int32_t main()':
traffickers.cpp:208:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  208 |         freopen(task".inp","r",stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
traffickers.cpp:209:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  209 |         freopen(task".out","w",stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...