首页 > 其他分享 >「赛后总结」20230724 CSP 模拟赛

「赛后总结」20230724 CSP 模拟赛

时间:2023-07-24 19:57:35浏览次数:50  
标签:代码 return 赛后 sum CSP ans inline ll 20230724

「赛后总结」20230724 CSP 模拟赛

点击查看目录

目录

想听歌,想看巨人,但是没有条件。

总结。

rk1 三个首杀,前二没有 HZOI 土著,前三没有 HZOI 2022 人,咋整的呀?

T1 5min 过掉样例交了一发,然后手玩一个样例不小心 Hack 掉了,改完了手玩一个样例又 Hack 掉了,最后对拍观察数据猜出正解,可见对拍的重要性。

T2 其实是有实力过的,赛时已经想到了 \(n^2\) 写法及优化,但是一直以为 \(n^2\) 暴力写假了就没时间去优化了,这种错觉的产生原因是搜索部分的暴力因为哈希冲突挂了,大概最后 20min 才发现。

T3 假二分能 65 分,据 xuany 说加特判 78 分,搬题人能不能用点心。

T4 看出来是状压但不会压。

这就是睡觉的重要性,实测多睡两个小时可以前进 11 名。

题解

T1 最长上升子序列 ARC125C

思路

sto Chen_jr orz

代码

点击查看代码
const ll N = 2e5 + 10;
namespace SOLVE {
	ll n, k, m, a[N], vis[N], ans[N];
	inline ll rnt () {
		ll x = 0, w = 1; char c = getchar ();
		while (!isdigit (c)) { if (c == '-') w = -1; c = getchar (); }
		while (isdigit (c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar ();
		return x * w;
	}
	inline void In () {
		n = rnt (), k = rnt (), m = 0;
		_for (i, 1, k) vis[a[i] = rnt ()] = 1;
		return;
	}
	inline void Solve () {
		ll j = 1;
		_for (i, 1, k - 1) {
			ans[++m] = a[i];
			while (vis[j]) ++j;
			if (j > a[i]) continue;
			ans[++m] = j, ++j;
		}
		for_ (i, n, a[k] + 1) if (!vis[i]) ans[++m] = i;
		ans[++m] = a[k];
		for_ (i, a[k] - 1, j) if (!vis[i]) ans[++m] = i;
		return;
	}
	inline void Out () {
		_for (i, 1, n) printf ("%lld ", ans[i]);
		puts ("");
		return;
	}
}

T2 独特序列 ARC125D

思路

设 \(f_i\) 表示以 \(i\) 结尾有多少个合法序列,有转移:

\[f_i = \sum_{j = 1}^{i - 1}(\prod_{k = j + 1}^{i - 1}[a_k\ne a_i][a_k\ne a_j])f_j \]

答案为:

\[\sum_{i = 1}^{n}(\prod_{k = i + 1}^{n}[a_k\ne a_i])f_i \]

预处理可做到 \(O(n^2)\)。

不难发现对于 \(j < i\),当且仅当 \(a_j\) 这个数在 \([1, i - 1]\) 中是最后一次出现时且 \((j, i)\) 中不存在 \(a_i\) 这个数时才会转移到 \(f_i\),那我们把没用的及时清零,使用 BIT 维护。

代码

点击查看代码
const ll N = 2e5 + 10, P = 998244353;

namespace BIT {
	class BIT {
	public:
		ll n;
	private:
		ll b[N];
		inline ll lowbit (ll x) { return x & -x; }
	public:
		inline void Update (ll x, ll y){
			if (x <= 0) return;
			while (x <= n) b[x] = (b[x] + y + P) % P, x += lowbit (x);
			return;
		}
		inline ll Query (ll x){
			ll sum = 0;
			while (x > 0) sum = (sum + b[x]) % P, x -= lowbit (x);
			return sum;
		}
	};
}

namespace SOLVE {
	ll n, a[N], la[N], f[N], vis[N], ans;
	BIT::BIT tr;
	inline ll rnt () {
		ll x = 0, w = 1; char c = getchar ();
		while (!isdigit (c)) { if (c == '-') w = -1; c = getchar (); }
		while (isdigit (c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar ();
		return x * w;
	}
	inline void In () {
		tr.n = n = rnt ();
		_for (i, 1, n) {
			a[i] = rnt ();
			la[i] = vis[a[i]], vis[a[i]] = i;
		}
		return;
	}
	inline void Solve () {
		_for (i, 1, n) {
			f[i] = (!la[i] + tr.Query (i - 1) - tr.Query (la[i] - 1) + P) % P;
			tr.Update (la[i], -f[la[i]]), f[la[i]] = 0, tr.Update (i, f[i]);
		}
		ans = tr.Query (n);
		return;
	}
	inline void Out () {
		printf ("%lld\n", ans);
		return;
	}
}

T3 最大 GCD ARC126C

思路

这玩意没有单调性,不能二分。

image

首先考虑能不能全加到最大值,能的话全加上去,还有剩余就平均分。

这个值域很小,那么枚举最大公约数,考虑如何快速判断解是否可行。即解不等式:

\[\begin{aligned} \sum_{i = 1}^{n}\left\lceil\frac{a_i}{x}\right\rceil - a_i &\le k\\ \sum_{i = 1}^{n}\left\lceil\frac{a_i}{x}\right\rceil &\le k + \sum_{i = 1}^{n}a_i \end{aligned} \]

考虑快速求左边这玩意,发现取值只有 \(\left\lceil\frac{\max_{i = 1}^{n}a_i}{x}\right\rceil\) 中,开个桶然后前缀和记录。

代码

点击查看代码
const ll N = 1e6 + 10;
namespace SOLVE {
	ll n, k, sum, mx, mn, a[N], t[N], ans;
	inline ll rnt () {
		ll x = 0, w = 1; char c = getchar ();
		while (!isdigit (c)) { if (c == '-') w = -1; c = getchar (); }
		while (isdigit (c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar ();
		return x * w;
	}
	inline bool Check (ll x) {
		ll q = -sum;
		_for (i, 1, (mx - 1) / x + 1) q += (t[i * x] - t[(i - 1) * x]) * i * x;
		return q <= k;
	}
	inline void In () {
		n = rnt (), k = rnt ();
		_for (i, 1, n) {
			a[i] = rnt ();
			++t[a[i]], sum += a[i];
			mx = std::max (mx, a[i]);
			mn = std::min (mn, a[i]);
		}
		return;
	}
	inline void Solve () {
		_for (i, 1, mx * 2) t[i] += t[i - 1];
		if (mx * n - sum <= k) {
			ans = mx + (k - mx * n + sum) / n;
			return;
		}
		for_ (i, mx, 1) if (Check (i)) { ans = i; break; }
		return;
	}
	inline void Out () {
		printf ("%lld\n", ans);
		return;
	}
}

T4 连续子段 ARC126D

思路

考虑状压。设 \(f_{i, j}\) 表示当前到了第 \(i\) 个数,当前排好的数的情况为 \(j\),考虑转移。

如果把 \(a_i\) 排进来,它肯定是从后往前移,次数为当前排好的数中比 \(a_i\) 大的数的数量。

不弄进来的话,当前序列还需要统一向右挪一次,或者让以后排进来的数多向左挪一次。

为方便直接设 \(s(x)\) 表示 \(\operatorname{popcount}(x)\),转移方程:

\[f_{i, j} = \min\{f_{i - 1, j\oplus 2^{a_i - 1}} + s(\left\lfloor\frac{j}{2^{a_i}}\right\rfloor), f_{i - 1, j} + s(j), f_{i - 1, j} + s(2^k - 1) - s(j)\} \]

可以滚一维。

代码

点击查看代码
const ll N = 210, S = 1 << 16, inf = 1ll << 40;
namespace SOLVE {
	ll n, k, a[N], f[S], ans;
	inline ll rnt () {
		ll x = 0, w = 1; char c = getchar ();
		while (!isdigit (c)) { if (c == '-') w = -1; c = getchar (); }
		while (isdigit (c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar ();
		return x * w;
	}
	inline ll Count (ll x) { ll s = 0; while (x) s += x & 1, x >>= 1; return s; }
	inline void In () {
		n = rnt (), k = rnt ();
		_for (i, 1, n) a[i] = rnt ();
		return;
	}
	inline void Solve () {
		memset (f, 0x3f, sizeof (f));
		f[0] = 0;
		_for (i, 1, n) {
			ll x = a[i];
			for_ (j, (1 << k) - 1, 0) {
				if (f[j] >= inf) continue;
				if (!((1 << (x - 1)) & j)) 
					f[j | (1 << (x - 1))] = std::min (f[j | (1 << (x - 1))], f[j] + __builtin_popcount (j >> (x - 1)));
				f[j] += std::min (__builtin_popcount (j), (int)(k) - __builtin_popcount (j));
			}
		}
		return;
	}
	inline void Out () {
		printf ("%lld\n", f[(1 << k) - 1]);
		return;
	}
}

标签:代码,return,赛后,sum,CSP,ans,inline,ll,20230724
From: https://www.cnblogs.com/Keven-He/p/contest-20230724.html

相关文章

  • 济南CSP-J刷题营集训
    Day1比赛T1方差求和可以用前缀和。求平均值时,特判是否整除而输出结果。求方差,我们直接用他给的公式以分数形式算出结果,维护两个分子和分母,通分相减后特判输出。注意要输出最简分数,所以我们用\(\textgcd\)约分。代码:#include<bits/stdc++.h>#definegtgetchar#define......
  • CSP 模拟 4
    今日推歌:SerenadeinG‘EinekleineNachtmusik’K525-WolfgangAmadeusMozart今天比赛直接搬的ARC125,126的CD题,那这样我也能出模拟赛(但是为什么HZOI2022都不写比赛题解,差评今天被HZOI2023,2024薄纱,我直接退役得了T1最长上升子序列考虑一个明显字典序不是......
  • 20230724日报
    简单的求和做题原因之前TLE30和TLE60,一直没有做出来做题过程想到了尺取法,重新听了尺取法的课,看了尺取法的模板。看了之前错误的代码,决定沿用之前使用map的方法,但是在找不出之前的错误,重新写了一遍代码交上去AC解题思路首先输入的元素是不需要按照它本来的顺序的(可以重......
  • 成语积累 20230724
    难兄难弟:nan4xiongnan4di:处于同样困境的人。(nan2:兄弟二人都非常好,难分高下。或讥讽两者同样低劣。出处:元方难为兄,季方难为弟。近义:难分伯仲)暴虎冯河:暴:通"虣",和老虎打斗;冯:通"淜",指无舟渡河。空手打虎,徒步过河。多用于比喻有勇无谋,冒险蛮干。也比喻勇猛果敢。例句:我原以为他......
  • CSP模拟3 <反思>
    t3:不要随便用mapt4:代码转移要删全首先考虑暴力,类似线段树,首先你要先dfs出每个节点子树的左右节点,然后修改查询时要考虑左儿子右边界是否大于查询左边界,右儿子左边界是否小于查询有边界,进行\(dfs\)\((46pts)\)点击查看代码#include<bits/stdc++.h>#defineintlonglongu......
  • CSP 模拟 3
    今天感觉很热,但是天气转凉的时候我也该退役了吧。今日推歌:透明哀歌-n-buna/Gumiecho-Crusher-P/GumiEnglish歌词Theclockstoppedticking,时钟停止发出嘀嗒声Foreverago.在很久以前HowlonghaveIbeenup?我究竟醒来了多久?Idon'tknow.我不知道Ican't......
  • CSP 模拟 2
    感觉像是noi模拟赛多了个pT1F咋做都行,但是考场上的正确做法被后来优化RE了,痛失60pts其中一种做法是考虑只有\(a_1\oplusb_i\)有可能成为答案,然后验证即可T2S定义dp状态\(f_{i,j,k,0/1/2}\)为用了\(i\)个红球,\(j\)个绿球,\(k\)个红球,并且最后一位是什么球......
  • P7074 [CSP-J2020] 方格取数 题解
    题目:题目描述设有n*m 的方格图,每个方格中都有一个整数。现有一只小熊,想从图的左上角走到右下角,每一步只能向上、向下或向右走一格,并且不能重复经过已经走过的方格,也不能走出边界。小熊会取走所有经过的方格中的整数,求它能取到的整数之和的最大值。输入格式第一行有两个整......
  • 「赛后总结」20230722 CSP 模拟赛
    「赛后总结」20230722CSP模拟赛点击查看目录目录「赛后总结」20230722CSP模拟赛反思题解T1回文思路代码T2快速排序思路代码T3混乱邪恶思路代码T4校门外歪脖树上的鸽子思路吓死我了我还以为K8He不更博了。为啥前天模拟赛不写啊?打过,没参加。为啥昨天模拟赛不......
  • CSP模拟3
    A.回文\(20\)多分的纯暴力搜索,\(A_{i,j}=A_{i-1,j+1}\)可以判完回文直接递推出路径数,共\(42\text{pts}\)。正解\(DP\)。回文可以转化一下思路,两个人分别从\((1,1),(n,m)\)出发,走的路径相同的方案数。设计\(dp[i][j][s][t]\)为第一个人在\((i,j)\)位置,第二个人在......