『模拟赛』多校A层冲刺NOIP2024模拟赛11

Rank

考前不挂就是赢

image

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++。


完结撒花~

image

posted @ 2024-10-22 18:14  DrRatio  阅读(72)  评论(3编辑  收藏  举报