求助 线段树合并的板子题QAQ
  • 板块学术版
  • 楼主YingLi
  • 当前回复2
  • 已保存回复2
  • 发布时间2020/10/30 21:53
  • 上次更新2023/11/5 09:28:27
查看原帖
求助 线段树合并的板子题QAQ
116824
YingLi楼主2020/10/30 21:53

传送门雨天的尾巴。这样写可以过前5个点,然后WA一排,再TLE一排QAQ是常数太大了吗……WA也不知道是为什么QAQ

做法就是对每个点动态开点权值线段树标记每个颜色,树上差分标记后线段树合并再查询最大值的颜色。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define maxn 100005
using namespace std;
typedef long long ll;
const int mx = 1e5;
int read() {
	int x = 0, f = 1, ch = getchar();
	while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
	while(isdigit(ch)) x = (x << 1) + (x << 3) + ch - '0', ch = getchar();
	return x * f;
}

struct edge {int to, nxt;} e[maxn << 1];
int head[maxn], k = 0;
void add(int u, int v) {e[k] = {v, head[u]}; head[u] = k++;}

int n, m;
int lg2[maxn], fa[maxn][20], dep[maxn];
void dfs(int u) {
	for(int i = 1; (1 << i) <= dep[u]; i++) fa[u][i] = fa[fa[u][i - 1]][i - 1];
	for(int i = head[u], v; ~i; i = e[i].nxt) {
		v = e[i].to; if(v == fa[u][0]) continue;
		fa[v][0] = u; dep[v] = dep[u] + 1;
		dfs(v);
	}
}

int LCA(int u, int v) {
	if(dep[u] > dep[v]) swap(u, v);
	while(dep[u] < dep[v]) v = fa[v][lg2[dep[v] - dep[u]] - 1];
	if(u == v) return u;
	for(int i = lg2[dep[u]]; i >= 0; i--) 
		if(fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
	return fa[u][0];
}

struct TREE {int l, r, x;} t[maxn << 6];
int tot, ans[maxn];
void change(int p, int l, int r, int x, int val) {
	if(l == r) {t[p].x += val; return;}
	register int mid = l + r >> 1;
	if(x <= mid) {if(!t[p].l) t[p].l = ++tot; change(t[p].l, l, mid, x, val);}
	else {if(!t[p].r) t[p].r = ++tot; change(t[p].r, mid + 1, r, x, val);}
	t[p].x = max(t[t[p].l].x, t[t[p].r].x);
}

int merge(int p, int q, int l, int r) {
//	printf("now:%d to %d\n", l, r);
	if(!p) return q; if(!q) return p;
	if(l == r) {t[p].x += t[q].x; return p;}
	register int mid = l + r >> 1;
	t[p].l = merge(t[p].l, t[q].l, l, mid);
	t[p].r = merge(t[p].r, t[q].r, mid + 1, r);
	t[p].x = max(t[t[p].l].x, t[t[p].r].x);
	return p;
}

int ask(int p, int l, int r) {
//	printf("now:%d to %d\n", l, r);
	if(l == r) {if(t[p].x) return l; return 0;}
	register int mid = l + r >> 1;
	if(t[t[p].l].x == t[p].x) return ask(t[p].l, l, mid);
	else return ask(t[p].r, mid + 1, r);
}

void dfs2(int u) {
	for(int i = head[u], v; ~i; i = e[i].nxt) {
		v = e[i].to; if(v == fa[u][0]) continue;
		dfs2(v);
		merge(u, v, 1, mx);
	}
	ans[u] = ask(u, 1, mx);
}

signed main() {
//	freopen("in.txt", "r", stdin);
//	freopen("out.txt", "w", stdout);
	n = read(), m = read(); memset(head, -1, sizeof head);
	for(int i = 1, u, v; i < n; i++) u = read(), v = read(), add(u, v), add(v, u);
	for(int i = 1; i <= n; i++) lg2[i] = lg2[i << 1] + 1;
	dfs(1); tot = n;
	for(int i = 1, u, v, w, lca; i <= m; i++) {
		u = read(), v = read(), w = read(); lca = LCA(u, v);
		change(u, 1, mx, w, 1), change(v, 1, mx, w, 1), change(lca, 1, mx, w, -1), change(fa[lca][0], 1, mx, w, -1);
	}
	dfs2(1);
	for(int i = 1; i <= n; i++) printf("%d\n", ans[i]);
	return 0;
}

2020/10/30 21:53
加载中...