12.24 CW 模拟赛 赛时记录
前言
考试期间, 只需要考虑考试策略即可, 别的都别管了
先打暴力, 想正解不超过
看题
现在看到不按难度排序已经免疫了, 感觉是防锅专用语?
#
题意非常清楚, 可能挖下性质还是可以做的
#
我不到啊, 但是
#
似
#
难评, 能不能做取决于前面的做不做出来
思路#
题意非常清楚, 但是还是理一下
你发现从
满足这个条件的基础上选择一个
首先我们考虑给定一个
先玩一下样例, 怎么看不懂?
抛开题面不谈, 这题问的应该是对于
不然样例都是错的
好的猜完题意, 我们考虑继续思考
这样做是简单的, 按照题意模拟每次排序即可, 到手
考虑优化,
显然的是每次操作只更新序列中的一个元素, 那么直接去排序一定不会是最优的, 怎么做可以快速的做到排序的效果?
注意到
每次更改一个数, 我们二分查找更改后这个数应该在哪里, 记为
唯一的问题是怎么求在
然后你发现这个贡献增大的值其实就是按照值排序后的后缀和, 那么这个题就解决了
实现#
框架#
首先对于原序列排序, 计算出初始的
对于每一次询问, 首先找到询问点的位置
记点的贡献为
时间复杂度
代码#
调了一会过掉了大样例, 确实不太好写
#include <bits/stdc++.h>
// #define FILE_IO
#define int long long
const int MAXN = 1.5e5 + 20;
int N, Q;
int a[MAXN];
int apre[MAXN];
int Tpre; // 最初的 T 值
int S[MAXN]; // 后缀和
signed main()
{
#ifdef FILE_IO
freopen("perm.in", "r", stdin);
freopen("perm.out", "w", stdout);
#endif
scanf("%lld", &N);
for (int i = 1; i <= N; i++) scanf("%lld", &a[i]), apre[i] = a[i];
std::sort(a + 1, a + N + 1);
for (int i = 1; i <= N; i++) Tpre += i * a[i];
for (int i = N; i >= 1; i--) S[i] = a[i] + S[i + 1];
scanf("%lld", &Q);
while (Q--) {
int x, y; scanf("%lld %lld", &x, &y);
int p = std::lower_bound(a + 1, a + N + 1, apre[x]) - a; // 找到询问点的位置
int pp; // 修改后的位置
int Tnow;
if (y > apre[x]) pp = std::upper_bound(a + 1, a + N + 1, y) - a - 1, Tnow = Tpre - p * a[p] + pp * y + S[pp + 1] - S[p + 1];
else pp = std::upper_bound(a + 1, a + N + 1, y) - a, Tnow = Tpre - p * a[p] + pp * y + S[pp] - S[p];
printf("%lld\n", Tnow);
}
return 0;
}
前言#
上一题其实还是不够冷静, 其实可以更快开到这里的, 大众分上不应该浪费太多时间
思路#
转化题意,
定义对
- 对于一个
- 对于
循环移位
看题的时候以为
玩下样例, 这个肯定是有性质的
好吧不太会做, 打完暴力跑路了
暴力是简单的, 你每次枚举翻转, 然后把
搞个迭代加深搜索应该能快一点, 应该能打掉
实现#
代码#
#include <bits/stdc++.h>
// #define FILE_IO
const int INF = 0x3f3f3f3f;
int T, N;
int ans = INF;
void IDdfs(int A, int B, int MaxDep, int NowDep) {
if (A == 0) { ans = std::min(ans, NowDep); return; }
if (NowDep >= MaxDep) return;
for (int i = 0; i < N; i++) { // 外层枚举 b 取反的位置
int nowA = A, nowB = B;
int Bi = (B >> i) & 1; nowB = B - (Bi << i) + ((!Bi) << i);
for (int j = 0; j < N; j++) // 对 a 进行取反
if ((nowB >> j) & 1) { int Ai = (A >> j) & 1; nowA = nowA - (Ai << j) + ((!Ai) << j); }
nowB <<= 1; nowB |= (nowB >> N) & 1; nowB &= ((1 << N) - 1); // 对 b 进行循环移位
IDdfs(nowA, nowB, MaxDep, NowDep + 1);
}
}
int main()
{
#ifdef FILE_IO
freopen("edit.in", "r", stdin);
freopen("edit.out", "w", stdout);
#endif
scanf("%d %d", &T, &N);
while (T--) {
std::string a, b; std::cin >> a >> b;
int A = 0, B = 0;
for (int i = 0, pow2 = 1; i < N; i++, pow2 *= 2) A += pow2 * (a[i] - '0'), B += pow2 * (b[i] - '0');
ans = INF;
for (int i = 1; i <= 25; i++) {
IDdfs(A, B, i, 0);
if (ans ^ INF) { printf("%d\n", ans); break; }
}
}
return 0;
}
调暴力太久了, 后面的题就算可做也很难写得完, 所以接下来全都打暴力
思路#
我们首先枚举保留的段落, 然后只要段落外的颜色与段落内的颜色不交即可删除这样一种情况
其实这个可以优化, 组合数学算一下就行了, 时间不够了
好像
先想一下
代码#
#
#include <bits/stdc++.h>
// #define FILE_IO
const int MAXN = 520; // 641
int Col[MAXN];
bool check(int l, int r, int n) {
bool vis[MAXN];
memset(vis, false, sizeof(vis));
for (int i = 1; i < l; i++) vis[Col[i]] = true;
for (int i = r + 1; i <= n; i++) vis[Col[i]] = true;
for (int i = l; i <= r; i++) if (vis[Col[i]]) return false;
return true;
}
int main()
{
#ifdef FILE_IO
freopen("del.in", "r", stdin);
freopen("del.out", "w", stdout);
#endif
int T; scanf("%d", &T);
while (T--) {
int n; scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &Col[i]);
int Ans = 0;
for (int l = 1; l <= n; l++) {
for (int r = l; r <= n; r++) {
if (check(l, r, n)) Ans++;
}
}
printf("%d\n", Ans);
}
return 0;
}
#
#include <bits/stdc++.h>
// #define FILE_IO
const int MAXN = 1e4 + 20; // 641
int Col[MAXN];
bool Check[MAXN][MAXN];
bool check(int l, int r, int n) {
bool vis[MAXN];
for (int i = 1; i <= n; i++) vis[i] = false;
for (int i = 1; i < l; i++) vis[Col[i]] = true;
for (int i = r + 1; i <= n; i++) vis[Col[i]] = true;
for (int i = l; i <= r; i++) if (vis[Col[i]]) return false;
return true;
}
int main()
{
#ifdef FILE_IO
freopen("del.in", "r", stdin);
freopen("del.out", "w", stdout);
#endif
int T; scanf("%d", &T);
while (T--) {
int n; scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &Col[i]);
for (int l = 1; l <= n; l++) {
for (int r = l; r <= n; r++) {
Check[l][r] = check(l, r, n);
}
}
int Ans = 0;
for (int l = 1; l <= n; l++) {
for (int r = l; r <= n; r++) {
if (Check[l][r]) Ans++;
}
}
printf("%d\n", Ans);
}
return 0;
}
容易发现
对于至多包含
具体的, 我不知道怎么打
代码#
#include <bits/stdc++.h>
// #define FILE_IO
const int MAXN = 1e6 + 20;
int Sum1[MAXN], Sum2[MAXN];
int LSY[MAXN];
int main()
{
int N, K;
scanf("%d %d", &N, &K);
std::string a, b; std::cin >> a >> b;
for (int i = N - 1; i >= 0; i--) Sum1[i] = Sum1[i + 1] + (b[i] == '1'), Sum2[i] = Sum2[i + 1] + (a[i] == '1');
int cnt = 0;
for (int i = 0; i < N; i++) {
if (b[i] == '0') LSY[++cnt] = Sum1[i];
}
cnt = 0;
int Ans = 0;
for (int i = 0; i < N; i++) {
if (a[i] == '0') Ans += std::abs(LSY[++cnt] - Sum2[i]);
}
printf("%d", Ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异