『模拟赛』多校A层冲刺NOIP2024模拟赛11
Rank
考前不挂就是赢
A. 冒泡排序
签,简单的有点格格不入。
发现错误代码实质上是将原序列划分成了若干个连通块,并对每个连通块做一遍排序。并查集维护,\(\mathcal{O(n)}\) 扫一遍合并连通块,然后按顺序输出即可。复杂度最坏 \(\mathcal{O(n\log n)}\)。
点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(register int (x) = (y); (x) <= (z); (x) ++)
#define fu(x, y, z) for(register int (x) = (y); (x) >= (z); (x) --)
using namespace std;
typedef long long ll;
#define lx ll
inline lx qr()
{
lx x = 0, f = 1; char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);
return x * f;
}
#undef lx
#define fi first
#define se second
#define pii pair<int, int>
#define P_B(x) push_back(x)
#define M_P(x, y) make_pair(x, y)
#define qr qr()
const int Ratio = 0;
const int N = 1e6 + 5;
int n, k;
int a[N], fx[N], tim[N];
vector<int> v[N];
bool yz[N];
namespace Wisadel
{
int Wfind(int x)
{
if(x == fx[x]) return x;
return fx[x] = Wfind(fx[x]);
}
short main()
{
freopen("bubble.in", "r", stdin) , freopen("bubble.out", "w", stdout);
n = qr, k = qr;
fo(i, 1, n) a[i] = qr, fx[i] = i;
fo(i, 1, n - 1)
{
if(i + k > n) break;
int _ = Wfind(i), __ = Wfind(i + k);
fx[__] = _;
}
fo(i, 1, n) v[Wfind(i)].P_B(a[i]);
fo(i, 1, n) if(v[i].size()) sort(v[i].begin(), v[i].end());
fo(i, 1, n)
{
int _ = Wfind(i);
printf("%d ", v[_][tim[_]++]);
}
puts("");
return Ratio;
}
}
int main(){return Wisadel::main();}
B. 染色
后面唯一的可做题(大概。
发现正着很难在计数的过程中去重,因此我们直接考虑最后的结果。关键的性质是:将原序列相邻项去重,可以操作得到的序列只能是它的子序列。手模还是好理解的。然后问题就很简单了,考虑设 \(f_{i,j}\) 表示以 \(i\) 结尾长度为 \(j\) 的方案数,转移显然有 \(f_{i,j}=1+\sum_{k\neq i}\ f_{k,j-1}\)。发现时间空间都是 \(\mathcal{O(n^2)}\) 的,直接上 bitset 优化,然后就做完了,复杂度 \(\mathcal{O(\frac{n^2}{w})}\)。
点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(register int (x) = (y); (x) <= (z); (x) ++)
#define fu(x, y, z) for(register int (x) = (y); (x) >= (z); (x) --)
using namespace std;
typedef long long ll;
#define lx ll
inline lx qr()
{
lx x = 0, f = 1; char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
for(; ch >= '0' && ch <= '9'; ch = getchar()) x = (x << 3) + (x << 1) + (ch ^ 48);
return x * f;
}
#undef lx
#define fi first
#define se second
#define pii pair<int, int>
#define P_B(x) push_back(x)
#define M_P(x, y) make_pair(x, y)
#define qr qr()
const int Ratio = 0;
const int N = 1e5 + 1, M = 2e4 + 1;
const int mod = 2;
int n, m, ans;
int a[N];
bitset<N> f[M], zc, tot;
namespace Wisadel
{
inline int Wc(int n, int m){return (n & m) == m;}
short main()
{
freopen("color.in", "r", stdin) , freopen("color.out", "w", stdout);
int T = qr;
while(T--)
{
n = qr, m = qr, ans = 0;
fo(i, 1, n) a[i] = qr;
fo(i, 1, m) f[i].reset();
tot.reset();
fo(i, 1, n)
{
int cz = a[i];
zc = tot ^ f[cz];// 其它结尾的方案数和
f[cz] = zc << 1;
f[cz][1] = 1;
tot = zc ^ f[cz];
}
fo(i, 1, n) ans ^= Wc(n - 1, i - 1) * tot[i] % 2;
printf("%d", ans);
}
return Ratio;
}
}
int main(){return Wisadel::main();}
C. 图
出题人说是套路题,然后 std 23k。
D. 山峦
简单(?)计数题。
挺温暖的,给爆搜送了 40pts,需要一点优化,不然会挂到 30~35pts。
题解做法用到什么高维前缀和优化,不会,std 写的依托,所以学了一个不知名大神的 75pts 做法,就是搜着转移。但是竖着搜需要开 \(n\times 184756\times m\) 的 dp 数组,速度也不够,然后就 GG 了。
期待一手晚上能改出来这道。
末
赤石场 ++。
厕所听到的
我前 10min 拿 100pts,后 230min 拿 4pts。
这难度梯度跨度我认可了。
nt 出题人压行还能打出 700 行 23k 的 std。
没挂分,rp++。