2025 CSP-S 模拟赛 12

2025 CSP-S 模拟赛 12

\(\text{Link}\)

倒序放题吗,有点意思。

得分

T1 T2 T3 T4 Sum Rank
\(100\) \(20\) \(23\) \(100\) \(243\) \(3/19\)

题解

T1 环游

容易发现 \(V\) 只会变化 \(\log V\) 次,每一次变化后我们可以走完一个连续的区间,最后要求我们走完整个区间。

把每一次变化看成一层,先不考虑没变的时候,在剩下的层中进行状压 dp。令 \(f_S\) 表示选完了 \(S\) 这些层,可以选出的最长前缀。\(g_S\) 类似的表示后缀。转移比较简单,复杂度 \(O(V\log V)\)

处理答案的时候先枚举前缀取的层,然后得出后缀取的层,根据 \(f_S\)\(g_T\) 求出它们可以给第一层中的那个连续段做贡献,那么这个连续段的答案就知道了。总复杂度是 \(O(V\log V)\) 的。

代码实现可能多了个老哥:

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

using namespace std;

const int Maxn = 2e5 + 5;
const int Inf = 5e9;
template <typename T> il void chkmax(T &x, T y) {x = (x >= y ? x : y);}
template <typename T> il void chkmin(T &x, T y) {x = (x <= y ? x : y);}
template <typename T>
il void read(T &x) {
	x = 0; char ch = getchar(); bool flg = 0;
	for(; ch < '0' || ch > '9'; ch = getchar()) flg = (ch == '-');
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
	flg ? x = -x : 0;
}
template <typename T>
il void write(T x, bool typ = 1) {
	static short Stk[50], Top = 0;
	x < 0 ? putchar('-'), x = -x : 0;
	do Stk[++Top] = x % 10, x /= 10; while(x);
	while(Top) putchar(Stk[Top--] | 48);
	typ ? putchar('\n') : putchar(' ');
}
il void IOS() {ios::sync_with_stdio(0); cin.tie(0), cout.tie(0);}
il void File() {freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout);}
bool Beg;

int n, V;
int x[Maxn], d[Maxn];
int v[Maxn], m;

int cnt[20], l[20][Maxn], r[20][Maxn];

int ans[Maxn];

int U, f[1 << 18], g[1 << 18];

bool End;
il void Usd() {cerr << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n"; }
signed main() {
	read(n), read(V);
	for(int i = 1; i <= n; i++) read(x[i]);
	x[0] = -Inf, x[n + 1] = Inf;
	for(int i = 0; i <= n; i++) d[i] = x[i + 1] - x[i];
	while(V) v[m++] = V, V >>= 1;
	v[m] = 0;
	for(int i = 0; i <= m; i++) {
		for(int j = 1; j <= n; j++) {
			if(d[j - 1] > v[i]) cnt[i]++, l[i][cnt[i]] = j;
			if(d[j] > v[i]) r[i][cnt[i]] = j;	
		}	
	}
	int U = (1 << m);
	for(int i = 0; i < U; i++) f[i] = 0, g[i] = n + 1;
	for(int i = 0; i < U; i++) {
		for(int j = 1; j <= m; j++) {
			if(i >> j - 1 & 1) continue;
			int p = upper_bound(l[j] + 1, l[j] + cnt[j] + 1, f[i]) - l[j] - 1;
			if(f[i] == l[j][p + 1] - 1) chkmax(f[i | (1 << j - 1)], r[j][p + 1]);
			else chkmax(f[i | (1 << j - 1)], r[j][p]);
		}
	}
	for(int i = 0; i < U; i++) {
		for(int j = 1; j <= m; j++) {
			if(i >> j - 1 & 1) continue;
			int p = lower_bound(r[j] + 1, r[j] + cnt[j] + 1, g[i]) - r[j];
			if(g[i] == r[j][p - 1] + 1) chkmin(g[i | (1 << j - 1)], l[j][p - 1]);
			else chkmin(g[i | (1 << j - 1)], l[j][p]);
		}
	}
	int flg = 0;
	for(int i = 0; i < U; i++) {
		int S = i, T = (U - 1) ^ i;
		if(f[S] >= g[T]) flg = 1;
		else {
			int p = upper_bound(l[0] + 1, l[0] + cnt[0] + 1, f[i]) - l[0] - 1;
			if(f[S] == l[0][p + 1] - 1) p++;
			if(g[T] <= r[0][p] + 1) ans[p] = 1;
		}
	}
	for(int i = 1; i <= cnt[0]; i++) {
		for(int j = l[0][i]; j <= r[0][i]; j++) {
			if(ans[i] || flg) puts("Possible");
			else puts("Impossible");
		}
	}
    Usd();
	return 0;
}

T2 数塔

看到中位数先考虑二分答案,用经典套路把原序列转化为 \(01\) 序列,然后只需要求出顶上的数字是 \(0\) 还是 \(1\) 即可。

考虑一个 \(01\) 交替连续段,如果两端颜色相同则这一段颜色都是这个,否则会分成左边一半和右边一半同色。找出中间位置所属的连续段并求解即可。复杂度 \(O(n\log n)\)

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

using namespace std;

const int Maxn = 2e5 + 5;
const int Inf = 2e9;
template <typename T> il void chkmax(T &x, T y) {x = (x >= y ? x : y);}
template <typename T> il void chkmin(T &x, T y) {x = (x <= y ? x : y);}
template <typename T>
il void read(T &x) {
	x = 0; char ch = getchar(); bool flg = 0;
	for(; ch < '0' || ch > '9'; ch = getchar()) flg = (ch == '-');
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
	flg ? x = -x : 0;
}
template <typename T>
il void write(T x, bool typ = 1) {
	static short Stk[50], Top = 0;
	x < 0 ? putchar('-'), x = -x : 0;
	do Stk[++Top] = x % 10, x /= 10; while(x);
	while(Top) putchar(Stk[Top--] | 48);
	typ ? putchar('\n') : putchar(' ');
}
il void IOS() {ios::sync_with_stdio(0); cin.tie(0), cout.tie(0);}
il void File() {freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout);}
bool Beg;

int T;
int n, m, a[Maxn];
int c[Maxn];

il int check(int mid) {
	for(int i = 1; i <= m; i++) c[i] = (a[i] >= mid);
	int ans1 = n - 1, ans2 = n - 1;
	for(int i = n; i >= 2; i--) {
		if(c[i] == c[i - 1]) {ans1 = n - i; break;}
	}
	for(int i = n; i < m; i++) {
		if(c[i] == c[i + 1]) {ans2 = i - n; break;}
	}
	int ans = min(ans1, ans2);
	if(ans & 1) return !c[n];
	else return c[n];
}

il void solve() {
	read(n); m = (n << 1) - 1;
	for(int i = 1; i <= m; i++) read(a[i]);
	int l = 1, r = m, res = 0;
	while(l <= r) {
		int mid = (l + r) >> 1;
		if(check(mid)) l = mid + 1, res = mid;
		else r = mid - 1;
	}
	write(res);
}

bool End;
il void Usd() {cerr << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n"; }
int main() {
	read(T);
	while(T--) solve();
    Usd();
	return 0;
}

T3 二择

注意到大小为 \(n\) 的匹配和大小为 \(n\) 的独立集加起来正好 \(3n\) 个点。所以我们找出原图的一个极大匹配,此时没有被选中的点必然构成一个独立集。这两部分必有一个满足条件,输出即可。

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

using namespace std;

const int Maxn = 5e5 + 5;
const int Inf = 2e9;
template <typename T> il void chkmax(T &x, T y) {x = (x >= y ? x : y);}
template <typename T> il void chkmin(T &x, T y) {x = (x <= y ? x : y);}
template <typename T>
il void read(T &x) {
	x = 0; char ch = getchar(); bool flg = 0;
	for(; ch < '0' || ch > '9'; ch = getchar()) flg = (ch == '-');
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
	flg ? x = -x : 0;
}
template <typename T>
il void write(T x, bool typ = 1) {
	static short Stk[50], Top = 0;
	x < 0 ? putchar('-'), x = -x : 0;
	do Stk[++Top] = x % 10, x /= 10; while(x);//dzbql
	while(Top) putchar(Stk[Top--] | 48);
	typ ? putchar('\n') : putchar(' ');
}
il void IOS() {ios::sync_with_stdio(0); cin.tie(0), cout.tie(0);}
il void File() {freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout);}
bool Beg;

int T;
int n, m;
int vis[Maxn], id[Maxn], cnt;

il void solve() {
	for(int i = 1; i <= 3 * n; i++) vis[i] = 0;
	read(n), read(m);
	cnt = 0;
	for(int i = 1, u, v; i <= m; i++) {
		read(u), read(v);
		if(!vis[u] && !vis[v]) id[++cnt] = i, vis[u] = vis[v] = 1;
	}
	if(cnt >= n) {
		puts("Beta2");
		for(int i = 1; i <= n; i++) write(id[i], 0); puts("");
	}
	else {
		puts("Beta1");
		cnt = 0;
		for(int i = 1; i <= 3 * n; i++) if(!vis[i]) id[++cnt] = i;
		for(int i = 1; i <= n; i++) write(id[i], 0); puts("");
	}
}

bool End;
il void Usd() {cerr << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n"; }
int main() {
	read(T);
	while(T--) solve();
    Usd();
	return 0;
}

T4 平衡

找规律。\(n\) 为偶数无解,\(n\) 为奇数仿照样例放一下即可。

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

using namespace std;

const int Maxn = 1e6 + 5;
const int Inf = 2e9;
template <typename T> il void chkmax(T &x, T y) {x = (x >= y ? x : y);}
template <typename T> il void chkmin(T &x, T y) {x = (x <= y ? x : y);}
template <typename T>
il void read(T &x) {
	x = 0; char ch = getchar(); bool flg = 0;
	for(; ch < '0' || ch > '9'; ch = getchar()) flg = (ch == '-');
	for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ 48);
	flg ? x = -x : 0;
}
template <typename T>
il void write(T x, bool typ = 1) {
	static short Stk[50], Top = 0;
	x < 0 ? putchar('-'), x = -x : 0;
	do Stk[++Top] = x % 10, x /= 10; while(x);
	while(Top) putchar(Stk[Top--] | 48);
	typ ? putchar('\n') : putchar(' ');
}
il void IOS() {ios::sync_with_stdio(0); cin.tie(0), cout.tie(0);}
il void File() {freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout);}
bool Beg;

int T;
int n, a[Maxn];

il void solve() {
	read(n);
	if(n % 2 == 0) {puts("NO"); return ;}
	puts("YES");
	int pos = n + 1;
	for(int i = 1; i <= n; i++) {
		int p1 = pos, p2 = (pos > n ? pos - n : pos + n);
		a[p1] = (i << 1) - 1, a[p2] = (i << 1);
		pos = p2 + 1;
	}
	for(int i = 1; i <= (n << 1); i++) write(a[i], 0);
	putchar('\n');
}

bool End;
il void Usd() {cerr << (&Beg - &End) / 1024.0 / 1024.0 << "MB " << (double)clock() * 1000.0 / CLOCKS_PER_SEC << "ms\n"; }
int main() {
	read(T);
	while(T--) solve();
    Usd();
	return 0;
}
posted @ 2025-07-07 16:35  UKE_Automation  阅读(90)  评论(0)    收藏  举报