#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, 0, numNode);
int t = t2 - t1;
int fullCount = t / numNode;
res += query(a, b, numNode - 1, numNode) * fullCount;
t1 %= numNode;
t2 %= numNode;
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:206:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
206 | freopen(task".inp","r",stdin);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
traffickers.cpp:207:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
207 | freopen(task".out","w",stdout);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |
| # | Verdict | Execution time | Memory | Grader output |
|---|
| Fetching results... |