Loading

3.13 CW 模拟赛 赛时记录

前言

策略 + 时间
数据检验, 不贪跟策略
心态冷静, 耐心, 放下, 不要浮躁

冲冲冲

看题

\(\rm{T1}\)

畏惧了, 这是啥啊
到时候在想

\(\rm{T2}\)

不是说放 \(\rm{T3}\)
我还没学高斯消元啊啊啊

啊啊啊, 感觉要爆, 这一点也不丁真

  • 概率与期望
    • \(\rm{dp}\) 特殊的点
      • 一定一定一定要分阶段
      • 可以先讨论那些更特殊的元素, 作为前阶段, 也就是说, 你可以在不影响概率的前提下处理阶段的优先级
    • 结束状态一定倒推, 开始状态一定正推
      • 按照规模 \(\rm{dp}\)
    • 期望 \(\rm{dp}\)
      • 全期望公式直接转移
      • 用期望定义
        • 可以求出每种情况的方案数,然后用期望定义得到答案
        • 先概率 \(\rm{dp}\)
      • 期望的线性性拆开考虑
      • 整体等概率一般可以拆成每一次均匀选择
    • 概率 \(\rm{dp}\)
      • 全概率公式直接转移

\(\rm{T3}\)

甚至是到现在最好理解的题目了

  • 点对问题
    • 区间问题
      • 往往可以转化成点对问题
      • 考虑单调性
    • 点对贡献维护, 类似扫描线的思路, 一维枚举
      • 一维数据结构处理
      • 往往可以通过之前计算过的 \(l\) 来继承, 类似 \(\rm{dp}\)
      • 一般来说, \(L\) 从右往左, \(R\) 从左往右枚举

\(\rm{T4}\)

同或运算是什么玩意啊, 啊啊啊
这个感觉也有转化方向, 到时候再说


好的今天的题看起来不是很友好
选择相信出题人升序排序, 先开 \(\rm{T1}\) , 然后看下 \(\rm{T3, T4}\) 暴力拿完 , 最后去看 \(\rm{T2}\) 能捞多少
每题时间差不多 \(\textrm{35 min}\) , 冷静

\(\rm{T1}\)

冷静, 耐心, 放下, 不浮躁
不贪跟策略, 数据检验

思路

本质上就是让你找到这样排序的数列的性质
疑似 \(50\) 就是直接处理

先找一下排序的性质, 看能不能找点规律方便处理
不简单就丢了

发现排序差不多就是依次把每个数拆成 \(1, 2, 3, \cdots\) 个质数然后放进去, 一点也不简单
显然还需要找到一个 \(50\%\) 的性质拼在一起

如果退而求其次你显然可以打个表过 \(50\%\) , 但是是没有什么拓展性, 还是先想有拓展性的, 要找性质再说打表


因此现在先找到 \(50\%\) 的性质\((\)简化问题为从 \(l = 1\) 开始\()\), 然后再想办法找新的性质

较好的性质是后面的序列可以表示为之前的某个序列加上一个质数, 但是没啥单调性, 很烦啊
发现这样做其实很美丽, 因为我们只需要依次枚举之前长度为 \(0, 1, 2, \cdots\) 的序列, 然后直接在末尾加数使其等于当前枚举的和, 一定符合性质


然后想了一会也没什么好的性质, 因为这样做一定要最前的内容才能递推, 用于打表应当是足够的, 但是仍然没有什么拓展性
因为 不能做题可以丢掉 , 所以差不多止步于此了

找不到一点性质了, 润去暴力了

实现

最终决定使用打表的方法去做, 先用上述方法写一份代码出来看看时间快不快
感性上来讲应该跑的挺快的

也就是

依次枚举之前长度为 \(0, 1, 2, \cdots\) 的序列, 然后直接在末尾加数使其等于当前枚举的和
注意剪枝


开始打之后发现实现写的太不完整了, 一点也不便于理解, 于是决定再想想再打

首先质数筛子预处理可以插入的数字, 然后最初只有空集, 每次就插入就行了
插入时动态维护之前所有长度为 \(k\) 的序列的 和-最大值 序列即可

打倒是打出来了, 但是文件太大了可能一会需要改一下, 但是因为浪费的时间太多应该先去开自己擅长的题目了
搞了半天把无打表的代码也写完了

\(\rm{T3}\)

冷静, 耐心, 放下, 不浮躁
不贪跟策略, 数据检验

  • 点对问题

    • 区间问题
      • 往往可以转化成点对问题
    • 点对贡献维护, 类似扫描线的思路, 一维枚举
      • 一维数据结构处理
      • 往往可以通过之前计算过的 \(l\) 来继承, 类似 \(\rm{dp}\)
      • 一般来说, \(L\) 从右往左, \(R\) 从左往右枚举
  • 根号分治

    • 适用: 复杂度一个跟个数有关, 一个跟大小有关
      个数少, 用个数处理问题
      个数多, 代表大小少, 用大小处理问题

      大小少, 用大小处理问题
      大小大, 代表个数少, 用个数处理问题

\(\rm{T1}\) 暴力用时太长, 应该尽量避免此种问题再次出现
也就是到现在为止, 速度仍然是最大的问题, 必须要反思方法了

思路

送了 \(40\)

初步的想法是通过之前计算过的 \(r\) 来继承, 类似 \(\rm{dp}\), 然后提前处理最近的合法序列这样
只要能够找到最近的合法序列的性质, 这题就做完了

首先能够确定的是没有单调性, 各种意义上的
最近需要多吃点蔬菜

发现我这个算法可以做完 \(m\) 比较大的, 考虑 \(m\) 比较小的时候怎么做
发现这个思路看起来好像直接寄了, \(\mathcal{O} (n \sqrt{n})\) 确实不够好

只要做完 \(n \leq 7 \times 10^4, m \leq 300\) , 就可以不掉分, 因此转而考虑值域比较小的时候的性质
好像只需要把这个 \(40\) 打了, 再去打 \(\rm{T4}\) \(30\) , 就不掉分了, 于是在剩下的时间里可以冷静一点了, 至少保底有了

哎哎哎, 感觉有希望, 这个递推是可优化的, 因为 \(\Delta\) 较小
但是发现一点也不好考虑, 无语了

想一下 \(n \leq 7 \times 10^4, m \leq 300\)\(\mathcal{O} (nm)\) 做法
差不多会了, 先去打完 \(\rm{T4}\) 回来干这个

写了 \(40\) , 冷静分析一下 \(n \leq 7 \times 10^4, m \leq 300\) 的性质
可以明确的是上面的 \(\rm{dp}\) 做法寄了

差不多会了一个 \(\mathcal{O} \Bigg(\dfrac{n^2}{m}\Bigg)\) 的做法, 可惜应该是打不完了

帮我解决其中 \(n \leq 7 \times 10^4, m \leq 300\) 的问题
使用 C++ 输出, 用 class 类封装, 其中我已经完成的部分如下

#include <bits/stdc++.h>
#define int long long
const int MAXN = 7e4 + 20;

int T;
int n, m;
int A[MAXN];

/*正常 dp*/
class worker1 {
private:
    int f[MAXN];
    int app[MAXN]; bool vis[MAXN];
    void init() {
        for (int i = 0; i <= n + 1; i++) f[i] = 0;
    }

public:
    void solve() {
        init();
        f[0] = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) app[j] = 0, vis[j] = false;
            int mx = 0, mn = 0x3f3f3f3f, tmp = 0;
            for (int j = i; j >= 1; j--) {
                app[A[j]]++; mx = std::max(mx, app[A[j]]), mn = std::min(mn, app[A[j]]);
                if (!vis[A[j]]) vis[A[j]] = true, tmp++;

                if (tmp == m && mx * m == i - j + 1) { f[i] += f[j - 1] + 1; break; }
            }
        }
        int ans = 0;
        for (int i = 1; i <= n; i++) ans += f[i];
        printf("%lld\n", ans);
    }
} sub1;

/*m 小*/
class worker2 {
private:
    std::vector<int> pos[320];
    int mcol = -1, tmp = 0x3f3f3f3f;
    void init() {
        for (int i = 1; i <= n; i++) pos[A[i]].push_back(i);
        for (int i = 1; i <= m; i++) {
            if (pos[i].size() < tmp) tmp = pos[i].size(), mcol = i;
        }
    }

public:
    void solve() {
        
    }
} sub2;

signed main() {
    scanf("%lld", &T);
    while (T--) {
        scanf("%lld %lld", &n, &m);
        for (int i = 1; i <= n; i++) scanf("%lld", &A[i]);

        if (n <= 7000 && m <= 7000) sub1.solve();
        else sub1.solve();
    }

    return 0;
}

你应该帮我填充 worker2 中的内容

\(\rm{T4}\)

冷静, 耐心, 放下, 不浮躁
不贪跟策略, 数据检验

思路

还能干啥, \(n 2^n\) 启动
话说 \(\LaTeX\) 还存在 \(\otimes\) 这个东西??

搞完了, 搞 \(\rm{T3}\) 去了

总结

速度仍然是最大的问题, 反思方法
多吃蔬菜

posted @ 2025-03-13 15:17  Yorg  阅读(23)  评论(0)    收藏  举报