首页 > 其他分享 >[赛记] 暑假集训CSP提高模拟26

[赛记] 暑假集训CSP提高模拟26

时间:2024-08-23 11:48:12浏览次数:6  
标签:26 赛记 int siz long fa tot include CSP

这场rank4,应该是暑假以来打的最好的一场了。。。
其它时候就没进过前10。。。

博弈 30pts

赛时 $ O(n^2) $ 暴力30pts;

对于暴力,我们能发现一个性质就是只要有一类边权出现了奇数次,那么先手必胜,所以我们枚举每一个点对,开个数组统计一下即可;

不要忘了离散化;

对于正解,用到了一个东西:$ xor-hashing $;

其实对于这种判断奇偶的问题,我们很容易想到 $ xor $,因为当有偶数个相同的数出现时, 他们 $ xor $ 起来的值是为 $ 0 $ 的,所以我们只需判断树上任意两点间的路径异或和是否为 $ 0 $ 即可;

那么我们做一下树上差分,记一下从根(指定一个)到每个点的异或和,然后找一下相同的减去其贡献即可(这是根据异或的性质:两个相同的数异或值为 $ 0 $, $ 0 \operatorname{xor} x = x $);

但是我们发现这样并不能保证正确性,比如 $ 1 \operatorname{xor} 2 \operatorname{xor} 3 = 0 $,但这种情况是先手必胜,判断出来是后手必胜,出现了冲突;

发现这其实很像 $ hash $,所以我们可以给每类边权随一个在 $ unsigned \ long \ long $ 范围内的值,这样正确判断的概率就很大了;

随权值的操作可以用mt19937_64 来实现;

其实思路过程可能应该是点分治,不行再到树上差分,再到异或,再到 $ xor-hashing $(当然赛时可能到不了);

这应该就是 $ xor-hashing $ 的基本应用了;

点击查看代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <ctime>
#include <cstdlib>
#include <random>
using namespace std;
int t;
int n;
int x[5000005], y[500005], w[500005], b[500005];
unsigned long long p[500005];
unsigned long long ha[500005];
map<unsigned long long, int> sum;
map<unsigned long long, bool> vis;
struct sss{
	int t, ne;
	unsigned long long w;
}e[1000005];
int h[1000005], cnt;
void add(int u, int v, unsigned long long ww) {
	e[++cnt].t = v;
	e[cnt].ne = h[u];
	h[u] = cnt;
	e[cnt].w = ww;
}
void dfs(int x, int fa) {
	sum[ha[x]]++;
	for (int i = h[x]; i; i = e[i].ne) {
		int u = e[i].t;
		if (u == fa) continue;
		ha[u] = ha[x] ^ e[i].w;
		dfs(u, x);
	}
}
long long ans;
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	mt19937_64 ran(time(0));
	cin >> t;
	for (int i = 1; i <= 500000; i++) {
		p[i] = ran();
	}
	while(t--) {
		cin >> n;
		cnt = 0;
		ans = 0;
		memset(h, 0, sizeof(h));
		memset(ha, 0, sizeof(ha));
		sum.clear();
		vis.clear();
		for (int i = 1; i <= n - 1; i++) {
			cin >> x[i] >> y[i] >> w[i];
			b[i] = w[i];
		}
		sort(b + 1, b + 1 + n - 1);
		int len = unique(b + 1, b + 1 + n - 1) - b - 1;
		for (int i = 1; i <= n - 1; i++) {
			add(x[i], y[i], p[lower_bound(b + 1, b + 1 + len, w[i]) - b]);
			add(y[i], x[i], p[lower_bound(b + 1, b + 1 + len, w[i]) - b]);
		}
		dfs(1, 0);
		for (int i = 1; i <= n; i++) {
			if (sum[ha[i]] && !vis[ha[i]]) {
				vis[ha[i]] = true;
				ans += 1ll * (sum[ha[i]] * (sum[ha[i]] - 1) / 2);
			}
		}
		cout << 1ll * n * (n - 1) / 2 - ans << '\n';
	}
	return 0;
}

大陆 100pts

赛时切了,还是首A。。。

其实这个题就是模拟一下即可;

考虑从下往上删子树,因为各个子树互不影响;

那么当我们回溯时,判断一下当前子树是否符合要求,若符合,则直接删掉;

这样我们会发现一个问题,就是可能会剩下一些点,这些点都和根组成一个连通块,且大小小于b;

那么我们想要把它们并入一个其它的,已划分出的连通块去,那么这个连通块的大小要小于等于2倍的b;

所以我们把划分条件改一下,当一棵子树的大小大于等于b且小于等于2倍的b时,就把它划出去;

那这样我们还会出现另一个问题,就是当一棵子树的子树很多时,可能出现这棵子树的大小大于2倍的b,但它的任意一棵子树的大小都小于b的情况,对于这种情况,我们直接单独考虑,每b个划分一次,不足b个的并入先前的连通块中,这样就满足要求了;

这样的话,我们划分出的最后一个连通块可能会大于2倍的b,小于3倍的b,这样就不能使根节点连的块并入此块,所以我们将这颗子树的根并入第一个连通块,因为第一个连通块大小是小于等于2倍的b的,这样就可以使根节点连的块并入第一个块了;

这题还是可以练练搜索能力的;

点击查看代码
#include <iostream>
#include <cstdio>
using namespace std;
int n, b;
struct sss{
	int t, ne;
}e[50005];
int h[50005], cnt;
void add(int u, int v) {
	e[++cnt].t = v;
	e[cnt].ne = h[u];
	h[u] = cnt;
}
int siz[50005];
int c[50005], tot, cap[50005], sum[50005], fa[50005];
int aa;
void dfs(int x, int f) {
	siz[x] = 1;
	fa[x] = f;
	for (int i = h[x]; i; i = e[i].ne) {
		int u = e[i].t;
		if (u == f) continue;
		dfs(u, x);
		siz[x] += siz[u];
	}
}
void cfs(int x) {
	c[x] = tot;
	sum[tot]++;
	for (int i = h[x]; i; i = e[i].ne) {
		int u = e[i].t;
		if (u == fa[x] || c[u]) continue;
		cfs(u);
	}
}
void efs(int x) {
	int su = 0;
	int ssu = 0;
	tot++;
	cap[tot] = x;
	sum[tot]++;
	c[x] = tot; //并入第一个块;
	for (int i = h[x]; i; i = e[i].ne) {
		int u = e[i].t;
		if (u == fa[x]) continue;
		if (c[u]) continue;
		su += siz[u];
		ssu += siz[u];
		cfs(u);
		if (su >= b) {
			tot++;
			if (siz[x] - ssu - 1 < b) {
				tot--;
			}
			cap[tot] = x;
			su = 0;
		}
	}
}
void afs(int x) {
	for (int i = h[x]; i; i = e[i].ne) {
		int u = e[i].t;
		if (u == fa[x]) continue;
		afs(u);
	}
	if (siz[x] >= b && siz[x] <= 2 * b) {
		tot++;
		cap[tot] = x;
		cfs(x);
		for (int i = fa[x]; i; i = fa[i]) {
			siz[i] -= siz[x];
		}
	} else if (siz[x] > 2 * b) {
		efs(x);
		for (int i = fa[x]; i; i = fa[i]) {
			siz[i] -= siz[x];
		}
	}
}
void ddfs(int x, int fa) {
	if (c[x]) {
		aa = c[x];
		return;
	}
	for (int i = h[x]; i; i = e[i].ne) {
		int u = e[i].t;
		if (u == fa) continue;
		ddfs(u, x);
	}
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> b;
	int x, y;
	for (int i = 1; i <= n - 1; i++) {
		cin >> x >> y;
		add(x, y);
		add(y, x);
	}
	dfs(1, 0);
	if (siz[1] >= b && siz[1] <= 3 * b) {
		cout << 1 << '\n';
		for (int i = 1; i <= n; i++) {
			cout << 1 << ' ';
		}
		cout << '\n';
		cout << 1;
		return 0;
	}
	afs(1);
	if (!c[1]) {
		aa = 0;
		ddfs(1, 0);
		for (int i = 1; i <= n; i++) {
			if (!c[i]) c[i] = aa;
		}
	}
	cout << tot << '\n';
	for (int i = 1; i <= n; i++) {
		cout << c[i] << ' ';
	}
	cout << '\n';
	for (int i = 1; i <= tot; i++) {
		cout << cap[i] << ' ';
	}
	return 0;
}

标签:26,赛记,int,siz,long,fa,tot,include,CSP
From: https://www.cnblogs.com/PeppaEvenPig/p/18375714

相关文章

  • 【论文解读】Macroblock Level Rate Control for Low Delay H.264/AVC based Video Co
    级别:IEEE时间:2015作者:MinGao等机构:哈尔滨工业大学下载:MacroblockLevelRateControlforLowDelayH.264/AVCbasedVideoCommunication摘要算法目的:提出了一种针对低延迟H.264/AVC视频通信的宏块(MB)级别速率控制算法。算法基础:基于ρ域速率模型,该模型涉......
  • 在CentOS7.9上 编译安装openssl-3.3.1+编译安装Nginx1.26.2
    编译安装注意事项知识点一:openssl的重要性openssl在Linux系统中扮演着至关重要的角色,尤其是在网络安全方面。许多服务和应用程序都依赖于openssl提供的加密功能,包括但不限于web服务器(如Apache和Nginx)、数据库服务器(如MySQL和PostgreSQL)、邮件服务器、VPN等。以下......
  • CSP 模拟 26
    T1博弈博弈策略是显然的,只有当所有数的数量全是偶数是,才是后手必胜,考虑随机异或哈希,找一遍后直接统计。T2跳跃容易想到的是一个\(\mathcal{O}(nk)\)的dp,但是带了\(k\),比较难处理。可以这样考虑,最后一定是到了一个位置\(x\),以\(x\)为右端点,在它的区间最大左端点之间反......
  • 暑假集训csp提高模拟27
    赛时rank17,T1100,T20,T30,T470T2一眼OSU的拓展版,懒得打了。T4写了一个奇怪的做法,轻轻松松拿70?T3读假题了,然后间接导致了我与STL和pbds斗智斗勇。题可能不算很难但是我糖线性只因用bitset记录每个数在二进制下的每一位,从高位到低位贪心即可。如果可以的数小于m个,那么就......
  • 『模拟赛』暑假集训CSP提高模拟27 || The End
    《$Never\;Over$》好久没推歌了。Idon'tknowwhattosayIdon'tknowwhattodoIjustwannagorightbacktoyouLikeacloudintheskyMytearsfallforyouIwouldpaintmylifeWhitejusttomakeyoublueCausebabyyouknowweshouldbetogethe......
  • csp模拟27-金箱子(题解)
    题目链接(显然还没有找到原题)虽说我现在才学会期望dp显得不太好,但没办法,谁让我比较菜~~,之前模拟赛已经考过几道类似的题了,但都一笔带过了,这次算是正式学习了一下这类题,于是就有了这篇题解。首先看到k次方首先想到的就是我们在进行dp转移的时候不太方便,这个时候很自然的想到二项......
  • 创新实践:流媒体服务器如何推动WebRTC支持H.265及JS硬软解码(MSE硬解、WASM软解)
    为了实现这一全面的解决方案,我们投入了近半年的时间进行调研与研发。我们的主要目标是:让流媒体服务器能够直接传输H.265编码的视频,而无需将其转码为H.264,从而使Chrome浏览器能够无缝解码并播放H.265视频。值得注意的是,目前市场上许多软硬件产品仍采用将H.265转码为H.264的方式来......
  • 创新实践:流媒体服务器如何推动WebRTC支持H.265及JS硬软解码(MSE硬解、WASM软解)
    为了实现这一全面的解决方案,我们投入了近半年的时间进行调研与研发。我们的主要目标是:让流媒体服务器能够直接传输H.265编码的视频,而无需将其转码为H.264,从而使Chrome浏览器能够无缝解码并播放H.265视频。值得注意的是,目前市场上许多软硬件产品仍采用将H.265转码为H.264的......
  • 暑假集训CSP提高模拟27
    暑假集训CSP提高模拟27组题人:@KafuuChinocpp\(T1\)P236.线性只因\(100pts\)诈骗题。部分分正解记\(opt\)表示待选集合,统计\(opt\)中这一位为\(1\)的数并加入临时集合\(tmp\)。若\(tmp\)大小\(\gem\)则加上这一位的贡献并将\(opt\)赋成\(tmp\)......
  • CSP防爆
    今日模拟赛T3把ac.inac.out愣是写成ac.txtac.txt自己在IDE里测大样例用的是.txt,提交没改过来100->0啊啊啊啊啊啊啊啊啊啊啊啊T6见祖宗0<=x<=1e9还要求和爆int但我没看见.....(100->90啊啊啊啊啊啊啊啊啊啊啊啊430->340经验考试绝不开多个页面,容易看错内存不紧......