当前位置: 代码迷 >> 综合 >> LOJ 2049「HNOI2016」网络
  详细解决方案

LOJ 2049「HNOI2016」网络

热度:40   发布时间:2024-03-07 22:08:29.0

要求最大值显然可以用二分求解,于是可以将所有询问的答案一起二分。
将所有的修改操作按照权值排序,那么对于每个点就要求出最大的一个不经过它的操作的权值,于是只需要统计出在它之前还有多少个操作,它被多少个操作覆盖,只要没有覆盖完,那么答案就在 mid+1...rmid + 1...rmid+1...r,否则在 l...midl ... midl...mid。可以将区间内操作按时间重排序,用树状数组维护树上差分。

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (int i = a; i <= b; i++)
#define per(i, a, b) for (int i = a; i >= b; i--)
const int inf = 0x3f3f3f3f;
const int mod = 1e9 + 7;
typedef long long LL;
typedef pair <int, int> P;
const int N = 2e5 + 5;int n, m, idx;
int st[N], ed[N], t[N], fa[N][20], bas[N], ans[N], d[N];
vector <int> g[N];void update_(int x, int k) {
     if (!x) return; for (; x <= n; x += x&-x) t[x] += k; }
int query_(int x) {
     int res = 0; for (; x; x -= x&-x) res += t[x]; return res; }
void dfs_(int u) {
    st[u] = ed[u] = ++idx, d[u] = d[fa[u][0]] + 1;for (int v, i = 0; i < (int) g[u].size(); i++) {
    v = g[u][i];if (v == fa[u][0]) continue;fa[v][0] = u;dfs_(v), ed[u] = ed[v];}
}
int cal_(int x, int y) {
    if (d[x] < d[y]) swap(x, y);int dif = d[x] - d[y];per (i, bas[dif], 0)if (dif&(1<<i)) x = fa[x][i];if (x == y) return x;per (i, bas[d[x]], 0)if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];return fa[x][0];
}int cnt_op, cnt_q, tim[N];struct Qu {
    int x, t, id;
} q[N], lq[N], rq[N];
struct Op {
    int v, x, y, z, k, t, ed;bool operator < (const Op &mpc) const {
     return v < mpc.v; }
} op[N];
struct Un {
    int typ, id, t;bool operator < (const Un &mpc) const {
     return t < mpc.t; }
} a[N];void solve_(int l, int r, int ql, int qr) {
    if (l > r || ql > qr) return;if (l == r) {
    rep (i, ql, qr) ans[q[i].id] = op[l].v;return;}int Sum = 0, mid = (l + r)>>1, tot = 0, tl = 0, tr = 0;rep (i, mid + 1, r) {
    a[++tot] = (Un) {
    0, i, op[i].t};a[++tot] = (Un) {
    0, i, op[i].ed};}rep (i, ql, qr)a[++tot] = (Un) {
    1, i, q[i].t};sort(a + 1, a + tot + 1);rep (i, 1, tot) {
    if (a[i].typ == 1) {
    int x = q[a[i].id].x;if (query_(ed[x]) - query_(st[x] - 1) == Sum) lq[++tl] = q[a[i].id];else rq[++tr] = q[a[i].id];} else {
    int k = op[a[i].id].t == a[i].t ? 1 : -1, x = op[a[i].id].x, y = op[a[i].id].y, z = op[a[i].id].z;update_(st[x], k), update_(st[y], k);update_(st[z], -k), update_(st[fa[z][0]], -k);Sum += k;}}rep (i, 1, tl)q[i + ql - 1] = lq[i];rep (i, 1, tr)q[ql + tl + i - 1] = rq[i];solve_(l, mid, ql, ql + tl - 1);solve_(mid + 1, r, ql + tl, qr);
}int main() {
    cin>>n>>m;for (int u, v, i = 1; i < n; i++) {
    scanf("%d%d", &u, &v);g[u].push_back(v), g[v].push_back(u);}dfs_(1);rep (i, 2, n) bas[i] = bas[i>>1] + 1;rep(k, 1, bas[n])rep (i, 1, n) fa[i][k] = fa[fa[i][k - 1]][k - 1];op[++cnt_op] = (Op) {
    0, 0, 0, 0, 1, 0, m + 1};//op[++cnt_op] = (Op) {0, 0, 0, 0, -1, m + 1};for (int typ, t, x, y, z, v, i = 1; i <= m; i++) {
    scanf("%d", &typ);if (typ == 0) {
    scanf("%d%d%d", &x, &y, &v);z = cal_(x, y);op[++cnt_op] = (Op) {
    v, x, y, z, 1, i};tim[i] = cnt_op;}if (typ == 1) {
    scanf("%d", &t);op[tim[t]].ed = i;}if (typ == 2) {
    scanf("%d", &x), ++cnt_q;q[cnt_q] = (Qu) {
    x, i, cnt_q};}}rep (i, 1, cnt_op)if (!op[i].ed) op[i].ed = m + 1;sort(op + 1, op + cnt_op + 1);solve_(1, cnt_op, 1, cnt_q);rep (i, 1, cnt_q)printf("%d\n", ans[i] ? ans[i] : -1);return 0;
}