2.27 CW 模拟赛 赛时记录
前言#
跟着策略做题, 注意数据检验, 不贪跟策略
一定要冷静, 放下, 耐心
看题#
#
给我打上麻将了, 真的假的
- 定义合法情况, 要求输出一组合法情况 / 合法情况的最值问题 / 求方案数
- 模拟操作情况, 找到最好开销, 注意最大和最小
- 列出合法情况需要满足的表达式, 在原序列中贪心选择最优情况
- 构造: 先推性质, 不行打表
- 找到不合法情况在什么时候出现, 通过对不合法情况的转化构造最优的合法情况
- 往往利用
, 结合约束处理当前方案 - 先找到一组合法解, 然后在基础上进行调整
- 一般优先考虑枚举性质更多, 或者确定性更强的元素
#
打表找规律, 可能有用
- 定义合法情况, 要求输出一组合法情况 / 合法情况的最值问题 / 求方案数
- 模拟操作情况, 找到最好开销, 注意最大和最小
- 列出合法情况需要满足的表达式, 在原序列中贪心选择最优情况
- 构造: 先推性质, 不行打表
- 找到不合法情况在什么时候出现, 通过对不合法情况的转化构造最优的合法情况
- 往往利用
, 结合约束处理当前方案 - 先找到一组合法解, 然后在基础上进行调整
- 一般优先考虑枚举性质更多, 或者确定性更强的元素
- 定义约束, 要求满足约束的情况数
- 逆向思维
- 考虑不满足约束的情况, 数学表示约束
#
- 交换相邻元素性质
- 从
到 , 交换 次 - 对于两个串的定位问题, 每个元素定位的花费就是关于其的逆序对个数
证明: 从大权值到小权值, 逐个固定位置 - 往往用固定之前的部分, 移动当前的部分来解决
- 从
- 定义合法情况, 要求输出一组合法情况 / 合法情况的最值问题 / 求方案数
- 模拟操作情况, 找到最好开销, 注意最大和最小
- 列出合法情况需要满足的表达式, 在原序列中贪心选择最优情况
- 构造: 先推性质, 不行打表
- 找到不合法情况在什么时候出现, 通过对不合法情况的转化构造最优的合法情况
- 往往利用
, 结合约束处理当前方案 - 先找到一组合法解, 然后在基础上进行调整
- 一般优先考虑枚举性质更多, 或者确定性更强的元素
#
不好, 最后一题放期望
那只能看看了
跟着策略走, 不贪, 数据检验
#
思路#
给定
要求把序列
题目显然提示先搞出桶, 所以记
记
转移只有两种
对于 , 各自使用 对于 , 一个数字单独使用 个
每次转移, 如果只是单独使用
否则转移到
现在的问题是, 对于
不妨枚举使用
那么如果
总复杂度是
不想数据检验, 先打一个试一下
挂的有点多, 先手搞一下
容易发现没考虑好
感觉可以用区间
令
初始化先预处理长度为
然后不难列出式子
只需要注意判断区间的合法性, 预处理长度为
有点担心这个的正确性, 先看下后面有没有更好拿的分
发现还是假的, 不妨修改定义
实现#
框架#
预处理
数组- 任意连续三个区间中, 有多少种情况把他们清零
必须使用至少一次 操作
转移
#
思路#
构造字典序最小的排列, 使得对于
对于位置
不太会, 不浪费时间了,
真瞪出来了
#include <bits/stdc++.h>
const int MAXN = 20;
int n, k;
int bas[MAXN], ans[MAXN];
int res[300020];
int main() {
scanf("%d %d", &n, &k);
if (n <= 10) {
memset(ans, 0x3f, sizeof ans);
for (int i = 1; i <= n; i++) bas[i] = i;
do {
bool flag = true;
for (int i = 1; i <= n; i++) {
if (std::abs(bas[i] - i) < k) { flag = false; break; }
}
if (flag) {
bool better = false;
for (int i = 1; i <= n; i++) {
if (ans[i] != bas[i]) {
if (ans[i] > bas[i]) better = true;
break;
}
}
if (better) {
for (int i = 1; i <= n; i++) ans[i] = bas[i];
}
}
} while (std::next_permutation(bas + 1, bas + n + 1));
if (ans[1] > n) printf("-1");
else for (int i = 1; i <= n; i++) printf("%d ", ans[i]);
} else {
int len = 2 * k;
for (int i = 1; i <= n; i += len) {
for (int j = i + k; j <= i + len - 1; j++) res[j - k] = j;
for (int j = i; j <= i + k - 1; j++) res[j + k] = j;
}
for (int i = 1; i <= n; i++) printf("%d ", res[i]);
}
return 0;
}
#
你想知道的还挺多
思路#
给定
一次交换定义为对
要求
但是这题拿个
#include <bits/stdc++.h>
const int MAXN = 11;
int n, W;
int w[MAXN];
std::vector<int> p;
std::map<std::vector<int>, bool> exists;
std::map<int, std::vector<int>> num; int cnt = 0;
void dfs(int now) {
for (int i = 2; i <= n; i++) {
if (w[num[now][i]] + w[num[now][i - 1]] <= W) {
std::vector<int> nxt = num[now];
std::swap(nxt[i], nxt[i - 1]);
if (exists[nxt]) continue;
else {
exists[nxt] = true, num[++cnt] = nxt;
dfs(cnt);
}
}
}
}
int main() {
scanf("%d %d", &n, &W);
p.resize(11);
for (int i = 1; i <= n; i++) scanf("%d", &p[i]);
for (int i = 1; i <= n; i++) scanf("%d", &w[i]);
exists[p] = true; num[++cnt] = p;
dfs(cnt);
std::vector<int> res; res.resize(11);
for (int i = 1; i <= n; i++) res[i] = 0x3f3f3f3f;
int ans = 0;
for (int i = 1; i <= cnt; i++) {
bool better = false;
for (int j = 1; j <= n; j++) {
if (res[j] != num[i][j]) {
if (res[j] > num[i][j]) better = true;
break;
}
}
if (better) {
for (int j = 1; j <= n; j++) res[j] = num[i][j];
}
}
printf("%d\n", cnt);
for (int j = 1; j <= n; j++) printf("%d ", res[j]);
return 0;
}
曹了呀, 大样例飞不过去, 怎么办怎么办怎么办
不管了, 急急急急急急, 直接去
#
思路#
直接模拟
对于一种状态
贪心的在他检票的时候, 如果当前没有票, 就买一张
不管了, 这题暴力先给我丢了, 先去冲
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现