首页 > 其他分享 >[题解] P5901 [IOI2009] Regions

[题解] P5901 [IOI2009] Regions

时间:2023-11-09 21:45:32浏览次数:43  
标签:P5901 颜色 int 题解 cnt Regions MAXN MAXM col

P5901 [IOI2009] Regions

给你一棵树,每个点有颜色 \(h_i\)。
多次询问,每次询问有多少对 \((u, v)\) 满足 \(u\) 是 \(v\) 的祖先且 \(u\) 的颜色是 \(r_1\) 且 \(v\) 的颜色是 \(r_2\)。
\(n, q \le 2 \times 10^5, h_i \le 2.5 \times 10^4\)。

总颜色数一定,考虑对颜色的出现次数根号分治。记阈值为 \(B\)。

当 \(r_1\)、\(r_2\) 颜色出现次数都 \(< B\) 时,我们直接枚举 \(r_1\) 中的每个点,数它的子树内的颜色为 \(r_2\) 的数的个数。这个记一下 dfs 序之后就是一维偏序,可以提前排好序,预处理时间复杂度 \(O(n \log n)\),单次查询时间复杂度 \(O(B)\)。

当其中一个出现次数 \(\ge B\) 时,由于颜色数较少,考虑预处理出答案。我们可以枚举每个颜色然后 dfs 预处理,时间复杂度 \(O(\frac{n^2}{B})\)。

当 \(B = \sqrt n\) 时,时间复杂度 \(O(n \sqrt n)\)。

constexpr int MAXN = 2e5 + 9, MAXM = 2.5e4 + 9, B = 400;
int n, m, q, h[MAXN], id[MAXN], dfn[MAXN], siz[MAXN],
	cnt[MAXM];
ll ans1[B][MAXM], ans2[B][MAXM];
vector<int> G[MAXN], s1, s2, a[MAXM];
vector<pair<int, int> > qry[MAXM];

void dfs0(int u) {
	static int dfc = 0;
	dfn[u] = ++ dfc, siz[u] = 1;
	for (auto v : G[u])
		dfs0(v), siz[u] += siz[v];
	return;
}
void dfs1(int u, int col, int cnt) {
	ans1[id[col]][h[u]] += cnt;
	cnt += (h[u] == col);
	for (auto v : G[u]) dfs1(v, col, cnt);
	cnt -= (h[u] == col);
	return;
}
int dfs2(int u, int col) {
	int cnt = 0;
	for (auto v : G[u])
		cnt += dfs2(v, col);
	ans2[id[col]][h[u]] += cnt;
	cnt += (h[u] == col);
	return cnt;
}

void slv() {
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	cin >> n >> m >> q >> h[1];
	for (int i = 2; i <= n; i ++) {
		int s; cin >> s >> h[i];
		G[s].emplace_back(i);
	}
	for (int i = 1; i <= n; i ++) cnt[h[i]] ++;
	for (int i = 1; i <= m; i ++)
		if (cnt[i] < B) id[i] = s1.size(), s1.emplace_back(i);
		else id[i] = s2.size(), s2.emplace_back(i);
	dfs0(1);
	for (int i = 1; i <= n; i ++) if (cnt[h[i]] < B)
		a[id[h[i]]].emplace_back(i);
	for (int i = 0; i < s1.size(); i ++) {
		sort(a[i].begin(), a[i].end(), [&](int x, int y) {
			return dfn[x] < dfn[y];
		});
		for (auto j : a[i]) {
			qry[i].emplace_back(dfn[j] - 1, -1);
			qry[i].emplace_back(dfn[j] + siz[j] - 1, 1);
		}
		sort(qry[i].begin(), qry[i].end(), [&](pii x, pii y) {
			return x.fir < y.fir;
		});
		for (auto &j : a[i]) j = dfn[j];
	}
	for (auto i : s2) dfs1(1, i, 0), dfs2(1, i);
	while (q --) {
		int r1, r2; cin >> r1 >> r2;
		if (cnt[r1] > B) cout << ans1[id[r1]][r2] << endl;
		else if (cnt[r2] > B) cout << ans2[id[r2]][r1] << endl;
		else {
			r1 = id[r1], r2 = id[r2];
			int cnt = -1; ll ans = 0;
			for (auto [u, op] : qry[r1]) {
				while (cnt + 1 < a[r2].size() && a[r2][cnt + 1] <= u)
					cnt ++;
				ans += op * (cnt + 1);
			}
			cout << ans << endl;
		}
	}
	return;
}

标签:P5901,颜色,int,题解,cnt,Regions,MAXN,MAXM,col
From: https://www.cnblogs.com/definieren/p/17822944.html

相关文章

  • [题解] CFgym103069G Prof. Pang's sequence
    G.Prof.Pang'ssequence给一个长度为\(n\)的序列\(a\),多次询问区间\([l,r]\)内有多少个子区间的颜色数是奇数。\(n,m\le10^5\)。先按照HH的项链的套路,对于每个数记一下\(lst_i\)表示\(a_i\)上一次出现的位置。然后扫描线,将所有子区间的答案转化成历史和。......
  • [CSP-J 2021] 小熊的果篮 题解
    题目链接既然只有两种东西,我们不妨分开考虑,这里也借鉴了很多二分图题目的切入点。假设苹果和桔子下标分别如下图所示:苹果:1367910桔子:2458那么第一次取,应该是这样取:1234689也就是先取开头比较小的,然后轮流取,注意一定保证递增,也就是对于苹果找出来的\(x\)......
  • [题解]CFgym103470E Paimon Segment Tree
    PaimonSegmentTree区间加,求一段时间内的区间平方和。\(n,m,q\le5\times10^4\)。对时间维差分一下,变成询问区间历史平方和。离线下来扫描线,扫描线维护时间维,数据结构维护序列维。考虑维护二元组\((a,s)\)表示当前位置值为\(a\),历史平方和为\(s\)。可以发现怎......
  • A2OJ Ladder 21 简要题解
    https://earthshakira.github.io/a2oj-clientside/server/Ladder21.html只记录Difficultylevel>=8的。有很多题是口胡的。写了的会标注提交记录。还有些很久以前写过的题就懒得搬提交记录了。71.CF444EDZYlovesplanting我们二分答案,然后可以这样转化:把权\(\ged\)的......
  • 题解:疯狂lcm
    %你赛打到一半来写个题解link:疯狂lcm题意,求:\[\sum_{i=1}^{n}lcm(i,n)\]不多说废话,直接开推:\[\begin{aligned}&=n\sum_{i=1}^{n}\frac{i}{gcd(i,n)}\\&=n\sum_{d\midn}\sum_{i=1}^{n}\frac{i}{d}[gcd(i,n)=d]\\&=n\sum_{d\midn}\sum_{i=1}^{n}......
  • KubeEdge部署 完美运行 附问题解决方法
    云端部署环境准备一、部署前工作(k8s、docker安装及配置、初始化集群、golang安装、keadm安装)配置网络参数cat>>/etc/hosts<<EOF#GitHubStart52.74.223.119github.com192.30.253.119gist.github.com54.169.195.247api.github.com185.199.111.153assets-cdn.gith......
  • linux/docker 版 Sql Server新建的数据库插入中文乱码问题解决方案
    SqlServer插入遇到乱码原因:在英文系统中,SqlServer默认排序规则为英文字典顺序解决方案一:容器版SqlServer,在创建容器时,可以加上环境变量-eMSSQL_COLLATION=Chinese_PRC_CI_AS-eTZ=Asia/Shanghai 把排序规则设为中文字典顺序并忽略大小写区分重音,时区设置为上海,不然......
  • CSP-S 2023 T1 题解
    CSP-S2023T1题解很简单,我们只需要暴力枚举五位密码,每次判断拨一个齿轮和两个齿轮能达到的状态数,如果等于\(n\),答案\(+1\)。时间复杂度\(O(10^5\times5n)\)。code#include<iostream>#include<algorithm>#include<cmath>#include<cstring>usingnamespacestd;......
  • P4069 题解
    简要题意给定一棵\(n\)个点的树,树有边权。对每个点维护一个集合\(S_u\),一开始集合均包含整数\(123456789123456789\)。设\({\rmdis}_{a,b}\)为树上两点\(a\),\(b\)的距离。共\(m\)次操作,分为如下两种:stab:设\(f\)为\(s\),\(t\)路径上的点集,对与\(\forall......
  • 上序问题解决补充(1)
    我发现好像只在idea里面整插件是不可以的你还需要下一个wampSERVER然后吧!他这个东西需要在法国官网下载,很他娘的慢,显示下载时间需要一天想不到吧我找到了中文站Wampserver3.3.064位官方版下载-WampServer中文站噔噔噔噔,闪亮登场......