[HNOI2016]树-缩点+倍增lca+主席树(码农)

本文深入探讨了高级数据结构如主席树、大物树及其在解决复杂算法问题中的应用。通过具体实例,展示了如何利用这些数据结构进行高效的数据查询和更新操作,特别关注于在图论和动态规划场景下的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门
博主心态已崩,打到一半在打啥都不知道
所以先挖坑,等心态恢复好了继续打
专业挖坑不填100年

#include <cstdio>
using namespace std;
struct TemplateTree {
	int tot = 0, lst[N], size[N], dfn[N], dep[N];
	
	struct Edge{
		int to, nxt;
	}e[N << 1];
	
	inline void add(int u, int v) {
		e[++cnt].to = v;
		e[cnt].nxt = lst[u];
		lst[u] = cnt;
	}
	
	inline void dfs(int x, int fa) {
		dfn[x] = ++tot;
		rk[tot] = x;
		size[x] = 1;
		dep[x] = dep[fa] + 1;
		for (int i = lst[x]; i; i = e[i].nxt) {
			int son = e[i].to;
			if (son == fa) continue;
			dfs(son, x);
			size[x] += size[son];
		}
	}
}tem;

struct ChairmanTree{
	struct Node{
		Node *ls, *rs;
		int sum;
		Node(Node *l = NULL, Node *r = NULL, int x = 0) {
			ls = l;
			rs = r;
			sum = x;
		}
	}*rt[N];
	
	inline void build(Node *&rt, int l, int r) {
		if (!rt) {
			rt = new Node();
		}
		if (l == r) return;
		int mid = l + r >> 1;
		build(rt -> ls, l, mid);
		build(rt -> rs, mid + 1, r);
	}
	
	inline Node *modify(Node *rt, int l, int r, int p) {
		Node *now = new Node(rt -> ls, rt -> rs, rt -> sum + 1);
		if (l == r) return now;
		int mid = l + r >> 1;
		if (p <= mid) now -> ls = modify(now -> ls, l, mid, p);
		else now -> rs = modify(now -> rs, mid + 1, r, p);
		return now;
	}
	
	inline int query(Node *L, Node *R, int l, int r, int kth) {
		if (l == r) return l;
		int mid = l + r >> 1, x = R -> ls -> sum - L -> ls -> sum;
		if (x >= kth) query(L -> ls, R -> ls, l, mid, kth);
		else query(L -> rs, R -> rs, mid + 1, rs, kth);
	}
	
	inline void make(*a) {
		for (int i = 1; i <= n; ++i) {
			rt[i] = modify(rt[i - 1], 1, n, a[i]);
		}
	}
}cmt;

struct BigTree{
	int all, id[N], ont[N];
	LL len[N];
	
	inline void doit(int wh, int x, int kth) {
		id[++all] = nds + 1;
		nds += tem.size[x];
		ont[all] = x;
		c[all][0] = wh;
		len[all][0] = cmt.dep[cmt.query(cmt.rt[cmt.dfn[x] - 1], cmt.rt[cmt.dfn[x] + cmt.size[x] - 1], 1, n, kth)];
		for (int i = 1; i < L; ++i) {
			c[all][i] = c[c[all][i - 1]][i - 1];
			len[all][i] = len[c[all][i - 1]][i - 1] + len[all][i - 1];
		}
	}
	
	inline LL query(LL x, LL y) {
		int xx = upper_bound(id + 1, id + all + 1, x) - id - 1;
		int yy = upper_bound(id + 1, id + all + 1, y) - id - 1;
		
	}
}bt;

int main() {
	scanf("%d%d%d", &n, &m, &q);
	for (int i = 1, x, y; i <= n; ++i) {
		scanf("%d%d", &x, &y);
		tem.add(x, y);
		tem.add(y, x);
	}
	tem.dfs(1, 0);
	cmt.build(rt[0], 1, n);
	cmt.make(tem.rk);
	bt.doit(1, 1, 1);
	for (int i = 1; i <= m; ++i) {
		int a;
		LL b;
		scanf("%d%lld", &a, &b);
		int id = upper_bound(bt.id + 1, bt.id + bt.all + 1, b) - bt.id - 1;
		bt.doit(id, a, b - bt.id[id] + 1);
	}
	while (q--) {
		LL fr, to
		scanf("%lld%lld", &fr, &to);
		printf("%lld\n", bt.query(fr, to));
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值