1.9 CW 模拟赛 赛时记录
前言
策略不变, 继续搞
看题
思路#
先考虑对于一个确定的
发现一个数能否被删除与删除的顺序无关, 本质上是因为
考虑到一个数能被删除, 仅当其在前后缀中都不为最大值, 也就是说可以
那么我们对于一个确定的
成功了, 考虑优化, 这题肯定是冲正解
这种类型的优化其实很典, 考虑不同前缀
你发现维护一个单调递增栈, 每次弹出时, 统计其对当前序列的贡献即可
实现#
框架#
维护一个单调递增栈, 每次弹出时, 统计其对当前序列的贡献即可
代码写短
代码#
#include <bits/stdc++.h>
#define int long long
const int MAXN = 1e5 + 20;
const int MOD = 998244353;
namespace calc {
int mul(int a, int b) { return a * b % MOD; }
int add(int a, int b) { return (a + b > MOD) ? a + b - MOD : a + b; }
int sub(int a, int b) { return (a - b < 0) ? a - b + MOD : a - b; }
void addon(int &a, int b) { a = add(a, b); }
void mulon(int &a, int b) { a = mul(a, b); }
} using namespace calc;
int pow2[MAXN];
int n;
int p[MAXN];
bool flag[MAXN]; // 记录是否为前缀最大值
struct monostack {
std::stack<int> s;
/*向单调栈中插入, 返回新增贡献*/
int push(int x) {
int res = 0;
while (!s.empty() && s.top() < x) {
if (!flag[s.top()]) res++;
s.pop();
}
s.push(x);
return res;
}
void clear() {
while (!s.empty()) s.pop();
}
} ms;
signed main()
{
pow2[0] = 1; for (int i = 1; i <= 100000; i++) pow2[i] = mul(pow2[i - 1], 2);
int T; scanf("%lld", &T);
while (T--) {
ms.clear();
scanf("%lld", &n);
for (int i = 1; i <= n; i++) scanf("%lld", &p[i]);
memset(flag, false, sizeof flag);
int mx = 0; for (int i = 1; i <= n; i++) if (p[i] > mx) mx = p[i], flag[p[i]] = true;
int ans = 0, res = 0;
for (int i = 1; i <= n; i++) {
res += ms.push(p[i]);
addon(ans, pow2[res]);
}
printf("%lld\n", ans);
}
return 0;
}
被简单题硬控约
目前得分:
思路#
一眼梦熊的题, 无敌了
题意有点神秘啊, 看不懂
摸下样例
博弈的题是有点困难的
考虑梦梦确定选择一个段时, 熊熊怎么选才能最大化最大子段和
这种情况下我们可以分类讨论
- 最大子段和跨过了梦梦 : 那么梦梦怎么选并不影响答案, 我们可以
求出这种情况下的答案, 需要贪心的放置数 - 最大子段和在梦梦的两侧 : 梦梦怎么选也不影响答案, 我们可以预处理
求出这种情况下的答案 - 最大子段和的一端在梦梦里面 : 考虑直接对于两种情况分两类讨论即可, 对于同种情况求最大, 对于不同种情况求最小
实现#
框架#
先预处理, 然后再分开计算答案
代码#
#include <bits/stdc++.h>
#define int long long
const int MAXN = 2025;
int n;
int A[MAXN], B[MAXN], C[MAXN << 1], C1[MAXN << 1];
int maxsum[MAXN][MAXN];
signed main()
{
int T; scanf("%lld", &T);
while (T--) {
scanf("%lld", &n);
for (int i = 1; i <= n; i++) scanf("%lld", &A[i]);
for (int i = 1; i <= n; i++) scanf("%lld", &B[i]);
for (int i = 1; i <= n; i++) C[i * 2] = std::min(A[i], B[i]), C[i * 2 - 1] = std::max(A[i], B[i]);
for (int l = 1; l <= n * 2; l++) {
if (l % 2 == 0) std::swap(C[l], C[l - 1]);
int maxsumr = 0, sumr = 0;
for (int r = l; r <= n * 2; r++){
sumr += C[r];
maxsumr = std::max(maxsumr, sumr);
maxsum[l][r] = maxsumr;
}
for (int r = l; r <= n * 2; r++) maxsum[l][r] = std::max(maxsum[l][r], maxsum[l][r - 1]);
}
for (int i = 1; i <= n; i++) C[i * 2] = std::max(A[i], B[i]), C[i * 2 - 1] = std::min(A[i], B[i]);
for (int i = 1; i <= n; i++) C1[i * 2] = std::min(A[i], B[i]), C1[i * 2 - 1] = std::max(A[i], B[i]);
int ans = 0x3f3f3f3f;
for (int i = 1; i <= n; i++) { // 外层枚举梦梦选择的段
int res = 0;
int suml = 0, maxsuml = 0;
for (int l = i * 2 - 2; l >= 1; l--) {
suml += C[l];
maxsuml = std::max(maxsuml, suml);
}
int sumr = 0, maxsumr = 0;
for (int r = i * 2 + 1; r <= n * 2; r++) {
sumr += C1[r];
maxsumr = std::max(maxsumr, sumr);
}
res = std::max(res, maxsuml + maxsumr + A[i] + B[i]);
res = std::max(res, maxsum[1][i * 2 - 2]);
res = std::max(res, maxsum[i * 2 + 1][n * 2]);
int a1 = std::min(A[i], B[i]) + maxsuml;
int a2 = std::max(A[i], B[i]) + maxsumr;
int b1 = std::max(A[i], B[i]) + maxsuml;
int b2 = std::min(A[i], B[i]) + maxsumr;
int ret = std::min(std::max(a1, a2), std::max(b1, b2));
res = std::max(res, ret);
ans = std::min(ans, res);
}
printf("%lld\n", ans);
}
return 0;
}
被
不行就把
反正这些题都没能力打正解, 不如直接把暴力打全
思路#
对于
只含
对于
实现#
框架#
考虑暴力模拟拿到
代码#
#include <bits/stdc++.h>
#define int long long
const int MAXN = 1e5 + 20;
const int MOD = 998244353;
namespace calc {
int mul(int a, int b) { return a * b % MOD; }
int add(int a, int b) { return (a + b > MOD) ? a + b - MOD : a + b; }
int sub(int a, int b) { return (a - b < 0) ? a - b + MOD : a - b; }
void addon(int &a, int b) { a = add(a, b); }
void mulon(int &a, int b) { a = mul(a, b); }
} using namespace calc;
int pow2[MAXN];
int n, q;
std::string S;
std::set<std::string> s;
signed main()
{
scanf("%lld %lld", &n, &q);
std::cin >> S; S = ' ' + S;
while (q--) {
int op, l, r; scanf("%lld %lld %lld", &op, &l, &r);
if (op == 1) for (int i = l; i <= r; i++) S[i] = '?';
else {
s.clear();
for (int St = 0; St < (1 << (r - l + 1)); St++) {
std::string nowS = "";
for (int i = l; i <= r; i++) {
if ((St >> (i - l)) & 1) nowS = nowS + S[i];
}
if (nowS[0] != '1') continue;
bool flag = true;
for (int i = 0; i < nowS.length(); i++) if (nowS[i] == '?') { flag = false; break; }
if (flag) s.insert(nowS);
}
printf("%lld\n", s.size());
}
}
return 0;
}
这题能拿
目前得分:
思路#
送了
考虑
代码#
#include <bits/stdc++.h>
int ans[11][11] = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 2, 1, 2, 1, 2, 2, 2},
{0, 1, 0, 0, 1, 0, 1, 0, 2, 1, 1},
{0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1},
{0, 2, 1, 1, 0, 1, 1, 1, 1, 0, }
};
int main()
{
int T; scanf("%d", &T);
while (T--) {
int x, y; scanf("%d %d", &x, &y);
if (x == 1 && y == 1) printf("0\n");
else {
printf("%d\n", ans[x][y]);
}
}
return 0;
}
无论结果如何, 尽力了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效