2025CSP-S模拟赛45 比赛总结

2025CSP-S模拟赛45

T1 T2 T3 T4
0 WA 0 WA 75 RE 10 WA

总分:85;排名:23/24。

T1 不但在傻逼题上浪费了 2h 而且挂了 100 分。

T1 染色(color)

傻逼题。不难发现没有任何一个质数是 4 的倍数,所以一直输出 1 2 3 4 即可。

#include <bits/stdc++.h>
#define il inline

using namespace std;

const int bufsz = 1 << 20;
char ibuf[bufsz], *p1 = ibuf, *p2 = ibuf;
#define getchar() (p1 == p2 && (p2 = (p1 = ibuf) + fread(ibuf, 1, bufsz, stdin), p1 == p2) ? EOF : *p1++)
il int read() {
	int x = 0; char ch = getchar(); bool t = 0;
	while (ch < '0' || ch > '9') {t ^= ch == '-'; ch = getchar();}
	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}
	return t ? -x : x;
}
bool Beg;
const int N = 1e4 + 10;
int n;
bool End;
il void Usd() {cerr << "\nUsed: " << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n";}
int main() {
	freopen("color.in", "r", stdin);
	freopen("color.out", "w", stdout);
	n = read();
	if (n == 1) return printf("1\n1\n"), 0;
	if (n == 2) return printf("1\n1 1\n"), 0;
	if (n == 3) return printf("2\n1 1 2\n"), 0;
	if (n == 4) return printf("2\n1 1 2 2\n"), 0;
	if (n == 5) return printf("3\n1 1 2 2 3\n"), 0;
	if (n == 6) return printf("3\n1 1 2 2 3 3\n"), 0;
	printf("4\n");
	for (int i = 1; i <= n; i++) {
		printf("%d ", (i - 1) % 4 + 1);
	}
	Usd();
	return 0;
}

T2 序列(array)

赛时这题没分纯粹 T1 浪费太久时间了。

不难发现,把 \(a_i\) 排序是不影响的。题目让求 \(\sum b_i+k \min b_i\) 的最大值,考虑枚举 \(v=\min b_i\),然后从前往后去最大化 \(b_i\),这显然是最优的。

然后感性理解以及打表可以发现,这个 \(ans\) 是关于枚举的这个 \(v\) 是一个单峰函数。就可以去一个的三分。

然后我也不知道哪里假了,反正最后会和正确答案差一些。原因我认为有两个,一个是我三分可能写的有问题,另一个是这个单峰函数中可能会有一些平的线段,然后就死了。

但是关注到和正确答案差的很小,于是我们可以一个的投机取巧。

#include <bits/stdc++.h>
#define il inline
#define int long long

using namespace std;

const int bufsz = 1 << 20;
char ibuf[bufsz], *p1 = ibuf, *p2 = ibuf;
#define getchar() (p1 == p2 && (p2 = (p1 = ibuf) + fread(ibuf, 1, bufsz, stdin), p1 == p2) ? EOF : *p1++)
il int read() {
	int x = 0; char ch = getchar(); bool t = 0;
	while (ch < '0' || ch > '9') {t ^= ch == '-'; ch = getchar();}
	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}
	return t ? -x : x;
}
bool Beg;
const int N = 2e5 + 10;
int n, m, kk, D, a[N];
int s;
il int getval(int v) {
	int sum = D - v * s;
	int res = kk * v + v * m;
	for (int i = 1; i <= m && sum >= a[i]; i++) {
		res += min(n - v, sum / a[i]);
		sum -= min(n - v, sum / a[i]) * a[i];
	}
	return res;
} 
int solve() {
	n = read(), m = read(), kk = read(), D = read();
	for (int i = 1; i <= m; i++) {
		a[i] = read();
	}
	sort(a + 1, a + 1 + m);
	s = 0;
	for (int i = 1; i <= m; i++) s += a[i];
	int L = 0, R = min(n, D / s), ans = 0;
	while (L <= R) {
		int m1 = L + (R - L + 1) / 3, m2 = R - (R - L + 1) / 3;
		if (getval(m1) < getval(m2)) {
			ans = m1;
			L = m1 + 1;
		} else {
			ans = m2;
			R = m2 - 1;
		}
	}
	int mx = 0;
	for (int i = max(0ll, ans - 100); i <= min(min(n, D / s), ans + 100); i++) { // 他既然差的不多那我就在他周围去 max 不就好了。。。
		mx = max(mx, getval(i));
	}
	printf("%lld\n", mx);
	
	return 0;
}
bool End;
il void Usd() {cerr << "\nUsed: " << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n";}
signed main() {
	freopen("array.in", "r", stdin);
	freopen("array.out", "w", stdout);
	int qq = read();
	while (qq--) {
		solve();
	}
	Usd();
	return 0;
}

T3 树上询问(query)

这个题其实不难。

考虑拆成两条链上的贡献。那么 \(a \rightarrow lca(a,b)\) 路径上的一点 \(x\) 满足条件等价于 \(dep_a-dep_x=x\),即 \(dep_x+x=dep_a\)。那么我们考虑对于每个点 \(x\),以 \(dep_x+x\) 为下标在桶这个位置上 \(+1\),然后因为是树链上的一段我们搞一个主席树 + 树剖即可。对于 \(lca(a,b) \rightarrow b\) 路径上的点同理。

#include <bits/stdc++.h>
#define il inline

using namespace std;

const int bufsz = 1 << 20;
char ibuf[bufsz], *p1 = ibuf, *p2 = ibuf;
#define getchar() (p1 == p2 && (p2 = (p1 = ibuf) + fread(ibuf, 1, bufsz, stdin), p1 == p2) ? EOF : *p1++)
il int read() {
	int x = 0; char ch = getchar(); bool t = 0;
	while (ch < '0' || ch > '9') {t ^= ch == '-'; ch = getchar();}
	while (ch >= '0' && ch <= '9') {x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar();}
	return t ? -x : x;
}
bool Beg;
const int N = 3e5 + 10;
int n, qq;
vector<int> G[N];
int fa[N], dep[N], top[N], siz[N], son[N], id[N], tot, rk[N];
il void dfs1(int x, int father) {
	fa[x] = father;
	dep[x] = dep[fa[x]] + 1;
	siz[x] = 1;
	for (int y : G[x]) {
		if (y == fa[x]) continue;
		dfs1(y, x);
		siz[x] += siz[y];
		if (siz[y] > siz[son[x]]) son[x] = y;
	}
}
il void dfs2(int x, int t) {
	top[x] = t;
	id[x] = ++tot;
	rk[tot] = x;
	if (!son[x]) return;
	dfs2(son[x], t);
	for (int y : G[x]) {
		if (y == fa[x] || y == son[x]) continue;
		dfs2(y, y);
	}
}
il int getlca(int x, int y) {
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		x = fa[top[x]];
	}
	if (dep[x] < dep[y]) swap(x, y);
	return y;
}
il int getdis(int x, int y) {
	return dep[x] + dep[y] - 2 * dep[getlca(x, y)];
}
int root1[N], root2[N];
struct Seg {
	struct node {
		int p, l, r, s;
	} tree[N << 5];
	#define lc tree[p].l
	#define rc tree[p].r
	int tot;
	il void build(int &p, int l, int r) {
		if (!p) p = ++tot;
		if (l == r) return;
		int mid = (l + r) >> 1;
		build(lc, l, mid), build(rc, mid + 1, r);
	}
	il void pushup(int p) {
		tree[p].s = tree[lc].s + tree[rc].s;
	}
	il int update(int p, int l, int r, int x, int v) {
		if (x > r) return p;
		int rt = ++tot;
		tree[rt] = tree[p];
		if (l == r) {
			tree[rt].s += v;
			return rt;
		}
		int mid = (l + r) >> 1;
		if (x <= mid) tree[rt].l = update(lc, l, mid, x, v);
		else tree[rt].r = update(rc, mid + 1, r, x, v);
		pushup(rt);
		return rt;
	}
	il int query(int p, int q, int l, int r, int x) {
		if (l == r) return tree[q].s - tree[p].s;
		int mid = (l + r) >> 1;
		if (x <= mid) return query(tree[p].l, tree[q].l, l, mid, x);
		else return query(tree[p].r, tree[q].r, mid + 1, r, x);
	}
} tr1, tr2;
il int query(int x, int y, int v) {
	int res = 0;
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		res += tr1.query(root1[id[top[x]] - 1], root1[id[x]], -n, n, v);
		x = fa[top[x]];
	}
	if (dep[x] < dep[y]) swap(x, y);
	res += tr1.query(root1[id[y] - 1], root1[id[x]], -n, n, v);
	return res;
}
il int query1(int x, int y, int v) {
	int res = 0;
	while (top[x] != top[y]) {
		if (dep[top[x]] < dep[top[y]]) swap(x, y);
		res += tr2.query(root2[id[top[x]] - 1], root2[id[x]], -n, n, v);
		x = fa[top[x]];
	}
	if (dep[x] < dep[y]) swap(x, y);
	res += tr2.query(root2[id[y]], root2[id[x]], -n, n, v);
	return res;
}
bool End;
il void Usd() {cerr << "\nUsed: " << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n";}
int main() {
	freopen("query.in", "r", stdin);
	freopen("query.out", "w", stdout);
	n = read(), qq = read();
	for (int i = 1; i < n; i++) {
		int x = read(), y = read();
		G[x].push_back(y);
		G[y].push_back(x);
	}
	dfs1(1, 0);
	dfs2(1, 1);
	tr1.build(root1[0], -n, n);
	tr2.build(root2[0], -n, n);
	for (int i = 1; i <= n; i++) {
		root1[i] = tr1.update(root1[i - 1], -n, n, dep[rk[i]] + rk[i], 1);
		root2[i] = tr2.update(root2[i - 1], -n, n, dep[rk[i]] - rk[i], 1);
	}
	while (qq--) {
		int x = read(), y = read();
		int lca = getlca(x, y);
		int res = query(x, lca, dep[x]) + query1(y, lca, 2 * dep[lca] - dep[x]);
		printf("%d\n", res);
	}
	Usd();
	return 0;
}

T4 网络(network)

posted @ 2025-09-14 19:27  Zctf1088  阅读(48)  评论(0)    收藏  举报