ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SP10707 COT2 - Count on a tree II

2022-04-07 22:35:14  阅读:153  来源: 互联网

标签:Count COT2 int siz top tree son dep void


\(\text{Solution}\)

统计树上 \(x\) 到 \(y\) 路径不同数的种类数
可以树上莫队
离线的树上莫队就是把树用欧拉序拍下来,然后和序列上的莫队一样即可

\(\text{Code}\)

#include <cstdio>
#include <algorithm>
#include <cmath>
#define RE register
#define IN inline
using namespace std;

const int N = 1e5 + 5;
int n, m, a[N], b[N], h[N], tot, dfc, rev[N], st[N], ed[N], ans[N];
int fa[N], dep[N], siz[N], son[N], top[N], bl[N], Ans, buc[N], used[N];
struct edge{int to, nxt;}e[N * 2];
IN void add(int x, int y){e[++tot] = edge{y, h[x]}, h[x] = tot;}
struct node{int l, r, id, z;}Q[N];
IN bool cmp(node a, node b){return ((bl[a.l] ^ bl[b.l]) ? a.l < b.l : ((bl[a.l] & 1) ? a.r < b.r : a.r > b.r));}

void dfs1(int x, int f)
{
	st[x] = ++dfc, rev[dfc] = x, fa[x] = f, dep[x] = dep[f] + 1, siz[x] = 1;
	for(RE int i = h[x]; i; i = e[i].nxt)
	{
		int v = e[i].to;
		if (v == f) continue;
		dfs1(v, x), siz[x] += siz[v];
		if (siz[v] > siz[son[x]]) son[x] = v;
	}
	ed[x] = ++dfc, rev[dfc] = x;
}
void dfs2(int x, int t)
{
	top[x] = t;
	if (son[x]) dfs2(son[x], t);
	for(RE int i = h[x]; i; i = e[i].nxt)
	{
		int v = e[i].to;
		if (v == fa[x] || v == son[x]) continue;
		dfs2(v, v);
	}
}
IN int LCA(int x, int y)
{
	while (top[x] ^ top[y])
	{
		if (dep[top[x]] > dep[top[y]]) x = fa[top[x]];
		else y = fa[top[y]];
	}
	return (dep[x] < dep[y] ? x : y);
}

IN void Del(int x){--buc[a[x]]; if (!buc[a[x]]) --Ans;}
IN void Add(int x){if (!buc[a[x]]) ++Ans; ++buc[a[x]];}
IN void update(int x){(used[x] ? Del(x) : Add(x)), used[x] ^= 1;}
void GetQ()
{
	for(RE int i = 1, x, y; i <= m; i++)
	{
		scanf("%d%d", &x, &y);
		if (st[x] > st[y]) swap(x, y);
		int lca = LCA(x, y);
		if (lca == x) Q[i] = node{st[x], st[y], i};
		else Q[i] = node{ed[x], st[y], i, lca};
	}
}
void solve()
{
	GetQ(), sort(Q + 1, Q + m + 1, cmp);
	int l = 1, r = 0;
	for(RE int i = 1; i <= m; i++)
	{
		while (l < Q[i].l) update(rev[l++]);
		while (l > Q[i].l) update(rev[--l]);
		while (r < Q[i].r) update(rev[++r]);
		while (r > Q[i].r) update(rev[r--]);
		if (Q[i].z) update(Q[i].z);
		ans[Q[i].id] = Ans;
		if (Q[i].z) update(Q[i].z);
	}
}

int main() 
{
	scanf("%d%d", &n, &m);
	for(RE int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i];
	sort(b + 1, b + n + 1); int len = unique(b + 1, b + n + 1) - b - 1;
	for(RE int i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + len + 1, a[i]) - b;
	for(RE int i = 1, x, y; i < n; i++) scanf("%d%d", &x, &y), add(x, y), add(y, x);
	dfs1(1, 0), dfs2(1, 1); int block = sqrt(n) + 1;
	for(RE int i = 1; i <= dfc; i++) bl[i] = i / block + 1;
	solve();
	for(RE int i = 1; i <= m; i++) printf("%d\n", ans[i]);
}

标签:Count,COT2,int,siz,top,tree,son,dep,void
来源: https://www.cnblogs.com/leiyuanze/p/16114589.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有