Sample
Input
13 23
1 2
1 3
2 4
2 5
3 6
3 7
4 8
4 9
6 10
6 11
7 12
7 13
2 1
0 8 13 3
0 9 12 5
2 9
2 8
2 2
0 10 12 1
2 2
1 3
2 7
2 1
0 9 5 6
2 4
2 5
1 7
0 9 12 4
0 10 5 7
2 1
2 4
2 12
1 2
2 5
2 3
Output
-1
3
5
-1
1
-1
1
1
3
6
7
7
4
6
Explanation
Explanation for Input
樣例給出的樹如下所示:
真是水得不行。
Code
#include <cstdio>
#include <iostream>
using namespace std;
int n, m, cnt, opt, head[100001], nx[200001], to[200001];
int fa[100001][18], size[100001], deep[100001], d[100001];
int mid, now, c[200001], num[200001], tmp[200001], Ans[200001];
struct Que {
int u, v, w, id, type;
} q[200001], q1[200001], q2[200001];
void addroad(int u, int v, int d) {
nx[d] = head[u], to[d] = v;
head[u] = d;
}
void build(int x, int pa) {
size[x] = 1, fa[x][0] = pa, deep[x] = deep[pa] + 1, d[x] = ++cnt;
for (int i = 1; i <= 17; i++) fa[x][i] = fa[fa[x][i - 1]][i - 1];
for (int i = head[x]; i; i = nx[i])
if (to[i] != pa) {
build(to[i], x);
size[x] += size[to[i]];
}
}
int get_lca(int u, int v) {
if (deep[u] < deep[v]) swap(u, v);
for (int i = 17; i >= 0; i--)
if (deep[fa[u][i]] >= deep[v]) u = fa[u][i];
for (int i = 17; i >= 0; i--)
if (fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
return u == v ? u : fa[u][0];
}
void add(int k, int x) {
if (!k) return;
k = d[k];
for (int i = k; i <= n; i += i & -i) c[i] += x;
}
int query(int k) {
int ans = 0;
for (int i = k; i > 0; i -= i & -i) ans += c[i];
return ans;
}
void Add(int u, int v, int x) {
int lca = get_lca(u, v);
add(u, x), add(v, x);
add(lca, -x), add(fa[lca][0], -x);
now += x;
}
void Solve(int L, int R, int l, int r) {
if (L > R) return;
if (l == r) {
for (int i = L; i <= R; i++)
if (q[i].type == 2) Ans[q[i].id] = l;
return;
}
mid = (l + r) >> 1, now = 0;
for (int i = L; i <= R; i++)
if (q[i].type != 2 && q[i].w >= mid)
Add(q[i].u, q[i].v, q[i].type == 1 ? -1 : 1);
else if (q[i].type == 2)
num[i] = now,
tmp[i] = query(d[q[i].u] + size[q[i].u] - 1) - query(d[q[i].u] - 1);
int len1 = 0, len2 = 0;
for (int i = L; i <= R; i++) {
if (q[i].type != 2) {
if (q[i].w >= mid)
Add(q[i].u, q[i].v, q[i].type == 1 ? 1 : -1), q2[++len2] = q[i];
else
q1[++len1] = q[i];
} else if (tmp[i] == num[i])
q1[++len1] = q[i];
else
q2[++len2] = q[i];
}
for (int i = 1; i <= len1; i++) q[L + i - 1] = q1[i];
for (int i = 1; i <= len2; i++) q[L + len1 + i - 1] = q2[i];
Solve(L, L + len1 - 1, l, mid);
Solve(L + len1, R, mid + 1, r);
}
int main() {
cin >> n >> m;
int u, v;
for (int i = 1; i < n; i++) {
scanf("%d%d", &u, &v);
addroad(u, v, i), addroad(v, u, i + n);
}
build(1, 0); //建樹,處理出樹上信息
cnt = 0;
for (int i = 1; i <= m; i++) {
scanf("%d", &opt);
q[i].type = opt;
if (opt == 0) scanf("%d%d%d", &q[i].u, &q[i].v, &q[i].w);
if (opt == 1) {
scanf("%d", &u);
q[i].u = q[u].u, q[i].v = q[u].v, q[i].w = q[u].w;
}
if (opt == 2) scanf("%d", &q[i].u), q[i].id = ++cnt;
}
Solve(1, m, 0, 1e9 + 1); //二分上界為最大權值 +1
for (int i = 1; i <= cnt; i++)
if (!Ans[i])
printf("-1\n");
else
printf("%d\n", Ans[i] - 1); //因為最後二分出的肯定不包括那條不經過的最大權值,所以二分得到的答案必定為
//ans+1 ,還要減掉
}
本文章為轉載內容,我們尊重原作者對文章享有的著作權。如有內容錯誤或侵權問題,歡迎原作者聯繫我們進行內容更正或刪除文章。