[CTSC2008]网络管理 动态主席树

题面

直接去洛谷看吧

题解

首先这是一道树上区间第k大的问题, 他求的是第k小, 转换一下就行

1、树剖+线段树套平衡树,查询时需要二分答案, 代码200行就出去了, 还是4个logn卡过去的

2、树剖+动态主席树(或者Kruskal重构树?),省去了2分, 3logn, 代码也是200+

3、作为个懒狗, 菜鸡这种200+的实在不友好, 复杂度也不友好

不管结构的话, 就是一个 动态第k大, 动态主席树秒了

然而这是颗树, 就有了树剖的logn

树剖有的dfs序是很巧妙的, 子树的序号是连续的

每次修改只影响子树, 而子树的编号又是连续的~

那我们就可以修改的时候是个区间修改!(当然先跑出来dfs序)

正好动态主席树就是树状(线段树维护的), 支持区间修改!

剩下的迎刃而解

什么你不知道怎么树上算值域个数?

在值域[l, r], (s, t)上的个数为, (root, s) + (root, t) - (root, lca(s, t)) - (root, father[lca(s, t)]);

2个优美的log, 收工

代码

#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n) * (n)
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
#define per(i, a, b) for (int i = (a); i >= (b); --i)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;

template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; }
template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; }
template<class T> void clear(T& a) { T().swap(a); }

const int N = 8e4 + 5;

struct STFrom {
	static const int N = 8e4 + 5;
	
	int f[N][20], dep[N], t;
	int *h, *ne, *to;

	void init(int n, int* H, int* Ne, int* To) {
		t = log2(n - 1) + 1;
		h = H, ne = Ne, to = To;
	}

	void bfs(int s) {
		queue<int> q;
		q.push(s); dep[s] = 1;
		rep (i, 0, t) f[s][i] = 0;

		while (!q.empty()) {
			int x = q.front(); q.pop();
			for (int i = h[x]; i; i = ne[i]) {
				int y = to[i];
				if (dep[y]) continue;
				dep[y] = dep[x] + 1;
				f[y][0] = x;

				for (int j = 1; j <= t; ++j)
					f[y][j] = f[f[y][j - 1]][j - 1];
				q.push(y);
			}
		}
	}

	int lca(int x, int y) {
		if (dep[x] > dep[y]) swap(x, y);
		per (i, t, 0) if (dep[f[y][i]] >= dep[x]) y = f[y][i];
		if (x == y) return x;
		per (i, t, 0) 
			if (f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
		return f[x][0];
	}

	int dist(int x, int y) {
		return dep[x] + dep[y] - (dep[lca(x, y)] << 1);
	}
} ST;

struct CHT {
    static const int M = 6e7;

    struct node {
        int val, lson, rson; /*int l, r; 值域*/
        node (int Val = 0, int Ls = 0, int Rs = 0)
            : val(Val), lson(Ls), rson(Rs){}
    } tr[N * 520]; //log2(sz)*log2(sz)*n

    int root[N], tot, qsc, qtc, quc, qwc, sz, n; // n为数组大小,sc为值域
    int qs[15], qt[15], qu[15], qw[15]; //log(n)

    void build(int n, int sz, int *a, PII *dfn) {
        this->sz = sz; this->n = n;
        for (int i = 1; i <= n; ++i)
            change(dfn[i].fi, a[i], 1), change(dfn[i].se + 1, a[i], -1);
    }

    void update(int &rt, int l, int r, int k, int cnt) {
        if (!rt) rt = ++tot;
        tr[rt].val += cnt;
        if (l == r) return;
        int mid = l + r >> 1;
        if (k <= mid) update(tr[rt].lson, l, mid, k, cnt);
        else update(tr[rt].rson, mid + 1, r, k, cnt);
    }

    void change(int x, int k, int cnt) { //n为最大区间长度
        for (int i = x; i <= n; i += i & -i)
            update(root[i], 0, sz, k, cnt);
    }

    int ask(int l, int r, int k) {
        if (l == r) return l;
        int sum = 0;
        for (int i = 1; i <= qsc; ++i) sum += tr[tr[qs[i]].lson].val;
        for (int i = 1; i <= qtc; ++i) sum += tr[tr[qt[i]].lson].val;
        for (int i = 1; i <= quc; ++i) sum -= tr[tr[qu[i]].lson].val;
        for (int i = 1; i <= qwc; ++i) sum -= tr[tr[qw[i]].lson].val;
        int mid = l + r >> 1;
        if (sum >= k) {
            for (int i = 1; i <= qsc; ++i) qs[i] = tr[qs[i]].lson;
            for (int i = 1; i <= qtc; ++i) qt[i] = tr[qt[i]].lson;
            for (int i = 1; i <= quc; ++i) qu[i] = tr[qu[i]].lson;
            for (int i = 1; i <= qwc; ++i) qw[i] = tr[qw[i]].lson;
            return ask(l, mid, k);
        } else {
            for (int i = 1; i <= qsc; ++i) qs[i] = tr[qs[i]].rson;
            for (int i = 1; i <= qtc; ++i) qt[i] = tr[qt[i]].rson;
            for (int i = 1; i <= quc; ++i) qu[i] = tr[qu[i]].rson;
            for (int i = 1; i <= qwc; ++i) qw[i] = tr[qw[i]].rson;
            return ask(mid + 1, r, k - sum);
        }
    }

    int preask(int s, int t, int u, int w, int k) {
        qtc = qsc = quc = qwc = 0;
        for (int i = s; i; i -= -i & i) qs[++qsc] = root[i];
        for (int i = t; i; i -= -i & i) qt[++qtc] = root[i];
        for (int i = u; i; i -= -i & i) qu[++quc] = root[i];
        for (int i = w; i; i -= -i & i) qw[++qwc] = root[i];
        return ask(0, sz, k);
    }
} bit;

int n, m, _, k;
int h[N], ne[N << 1], to[N << 1], tot;
int op[N], x[N], y[N];
int a[N], df;
PII dfn[N];

void add(int u, int v) {
    ne[++tot] = h[u]; to[h[u] = tot] = v;
}

void dfs(int x, int f) {
    dfn[x].fi = ++df;
    for (int i = h[x]; i; i = ne[i]) {
        int y = to[i];
        if (y == f) continue;
        dfs(y, x);
    }
    dfn[x].se = df;
}

int main() {
    IOS; cin >> n >> m; VI c;
    rep (i, 1, n) cin >> a[i], c.pb(a[i]);
    rep (i, 2, n) {
        int u, v; cin >> u >> v;
        add(u, v); add(v, u);
    }

    rep (i, 1, m) {
        cin >> op[i] >> x[i] >> y[i];
        if (!op[i]) c.pb(y[i]);
    }
    sort(all(c)); c.erase(unique(all(c)), c.end());
    rep (i, 1, n) a[i] = lower_bound(all(c), a[i]) - c.begin();
    rep (i, 1, m) if (!op[i]) y[i] = lower_bound(all(c), y[i]) - c.begin(); 

    ST.init(n, h, ne, to); ST.bfs(1);
    dfs(1, 0); bit.build(n, c.size(), a, dfn);
    rep (i, 1, m) {
        if (!op[i]) {
            bit.change(dfn[x[i]].fi, a[x[i]], -1);
            bit.change(dfn[x[i]].se + 1, a[x[i]], 1);
            a[x[i]] = y[i];
            bit.change(dfn[x[i]].fi, a[x[i]], 1);
            bit.change(dfn[x[i]].se + 1, a[x[i]], -1);
        } else {
            int k = ST.dist(x[i], y[i]) + 2 - op[i], lca = ST.lca(x[i], y[i]);
            if (k <= 0) cout << "invalid request!
";
            else cout << c[bit.preask(dfn[x[i]].fi, dfn[y[i]].fi,
                dfn[lca].fi, dfn[ST.f[lca][0]].fi, k)] << '
';
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/2aptx4869/p/13995982.html