当前位置: 首页 > news >正文

CSP-S 41多校 9

10.28

CSP-S 前倒数第二场模拟赛,直接一道都没切出来。。。

再不放信心赛真要没信心了。

t1

dp题。

显然对于每一次行动都是一个背包dp。

变种在于背包更换,更换后容量重新计算

所以记 \(las_i\) 表示到第 \(i\) 个物品时最大价值,每次背包转移前先与 \(las\)\(\max\) 即可(表示换背包)。

然后发现时间复杂度是 \(O(mnV)\) 的,约为4e9 。

不可过呜呜呜

赛时就到这里了(oj神机发力了,大数据有一多半跑过了,986ms左右,最终85pts)。

赛后茅塞顿开:

还有一个条件没用上!

背包的容量单调不减

背包很多有1e5个,而值域很小只到200,也就是说有大量的背包是被浪费的,根本不用转移!

所以我们只需对后200个背包dp即可(因为后200个背包可代表所有背包)。

时间复杂度骤降为\(O(n^2V)\)

所以赛后改了下范围就过了(甚至最优解第三,小常数发力了)。

赛后乱搞发现我的赛时代码(即\(O(mnV)\)版)经过卡常,在评测机心情好的情况下可以90pts(理论最高是95pts,两次取或),神机啊!(accoder机子就只有60pts好吧)

神机发力了

code

只改范围的赛时代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const int V = 210;
int n, m;
int wei[V], val[V];
int spa[N];
int dp[V][V]; // i,j,k: m,ed,spa
int las[V];inline int max(int a, int b) { return a > b ? a : b; }signed main()
{freopen("axis.in", "r", stdin);freopen("axis.out", "w", stdout);ios::sync_with_stdio(0);cin.tie(0);cin >> n >> m;for (int i = 1; i <= n; ++i)cin >> wei[i] >> val[i];for (int i = 1; i <= m; ++i)cin >> spa[i];for (int i = max(m - 200, 1); i <= m; ++i){for (int j = 1; j <= n; ++j) // ed{for (int k = spa[i]; ~k; --k){dp[j][k] = max(dp[j - 1][k], las[j]);if (k - wei[j] >= 0)dp[j][k] = max(dp[j][k], dp[j - 1][k - wei[j]] + val[j]);}for (int k = spa[i]; ~k; --k)las[j] = max(las[j], dp[j][k]);}}cout << dp[n][spa[m]] << "\n";return 0;
}

t2

神秘结论题。

没看出结论直接爆。

结论:

对于每个给对给定的左,右端点(\(l,r\)),答案为\(2*(r-l+1)-len-1\) ,其中 \(len\) 为选取的点的个数。

所以只需枚举 \(l,r\) 然后对于每个 \(l,r\) 找到最大的合法的 \(len\) 即可。

拿两个优先队列就可以维护(一定要注意顺序)。

code

嘟嘟哒哒
#include <bits/stdc++.h>
using namespace std;
const int N = 1e3 + 10;
const int inf = 1e9 + 7;
int n, k;
int w[N];
priority_queue<int, vector<int>, greater<int>> in;
priority_queue<int> out;signed main()
{freopen("circle.in", "r", stdin);freopen("circle.out", "w", stdout);ios::sync_with_stdio(0);cin.tie(0);cin >> n >> k;int sum = 0, maxn = -inf;for (int i = 1; i <= n; ++i){cin >> w[i];maxn = max(maxn, w[i]);sum += (w[i] >= 0 ? w[i] : 0);}if (maxn >= k){cout << 0;return 0;}if (sum < k || k <= 0){cout << -1;return 0;}int ans = inf;for (int i = 1; i <= n; ++i){while (in.size())in.pop();while (out.size())out.pop();sum = 0;int len = 0;for (int j = i; j <= n; ++j){// cerr << "j=" << j << "\n";sum += w[j], ++len;if (w[j] < 0)in.push(w[j]);while (in.size() && sum < k){// cerr << "j=" << j << "\n";sum -= in.top(), out.push(in.top()), in.pop(), --len;}if (sum < k)continue;// cerr << "!!j=" << j << " siz=" << out.size() << "\n";while (out.size() && sum + out.top() >= k){// cerr << "%%%j=" << j << "\n";sum += out.top(), in.push(out.top()), out.pop(), ++len;}ans = min(ans, (j - i + 1) * 2 - len - 1);}}cout << ans;return 0;
}

t3

赛时被环卡了 1h.

赛后才发现原来题也读假了。。。

原题面中的字典序不是针对字符的,而是指各编号的大小比较,就是按数值比。

我场上还将特意所有编号转成字符串然后排序。

正解:

发现\(n,m\)都很小,甚至\(O(nq)\)也是可接受的。

于是考虑直接暴力做。

但是在线判断贪心取最小的同时判断环还是太困难了(我不会),考虑先处理部分信息。

先对每个点dfs将连通处理出来,之后记\(f_{j,i}\)表示\(j\)\(i\)的路径上最小的点

在之后查询时因为已知终点,所以可以直接将路径复现。

开个数组将路径存一下就行了。

还是注意特判。

时间复杂度\(O(n(n+m+q))\),虽然看着很可怕但它大概8e8,所以可过。

附唐诗记录

code

哩哩啦啦
#include <bits/stdc++.h>
using namespace std;
const int N = 2e3 + 10;
int n, m, q, type;
int vis[N][N];
int f[N][N];
vector<int> e[N];
int flag[N], stk[N], top, las;inline void dfs(int x, int op)
{if (vis[op][x])return;vis[op][x] = 1;for (auto y : e[x])dfs(y, op);
}signed main()
{freopen("path.in", "r", stdin);freopen("path.out", "w", stdout);ios::sync_with_stdio(0);cin.tie(0);cin >> n >> m >> q >> type;for (int i = 1, u, v; i <= m; ++i){cin >> u >> v;e[u].emplace_back(v);}for (int i = 1; i <= n; ++i)sort(e[i].begin(), e[i].end());for (int i = 1; i <= n; ++i){memset(f[i], 0x3f, sizeof(f[i]));dfs(i, i);}// cerr << "!\n";for (int i = 1; i <= n; ++i)for (int j = 1; j <= n; ++j)if (vis[i][j])for (auto k : e[i])if (vis[k][j])f[j][i] = min(f[j][i], k);// cerr << "!\n";las = 1;int x, y, k;while (q--){cin >> x >> y >> k;if (type)x = (x ^ las) % n + 1, y = (y ^ las) % n + 1, k = (k ^ las) % n + 1;// cerr << "q=" << q << "!\n";if (!vis[x][y]){cout << "-1\n";// cerr << "x=" << x << " y=" << y << "\n";las = 1;continue;}top = 1, stk[1] = x;flag[x] = q + 1;// cerr << "x=" << x << " y=" << y << "\n";while (stk[top] != y) // 以终点为目标,从前往后压入点{int u = f[y][stk[top]];// cerr << "u=" << u << "\n";if (flag[u] == q + 1){top = 0;break;}stk[++top] = u;flag[u] = q + 1;}if (top < k)cout << "-1\n", las = 1;else{las = stk[k];cout << las << "\n";}}return 0;
}

t4

原题黑?

咕。

http://www.jsqmd.com/news/24937/

相关文章:

  • 【25.10.28】模拟赛
  • CSP-S模拟41
  • Linux双中文编码笔记
  • C++类和对象(1) - 详解
  • 人工智能之编程基础 Python 入门:第二章 Python 的编辑器 VS Code
  • 2019 福建省队集训录
  • AIX multibos bootlist
  • 记录一次nginx能通但是请求一直不了的问题
  • 【嵌入式】PWM DAC的滤波器设计
  • 被称作遗憾之物 爬满了脊骨 又把控了痛楚 被称作无用之物 修筑了唯一的通路
  • neovim在windwos11下snack.nvim的问题
  • 完整教程:Java 集合 “List + Set”面试清单(含超通俗生活案例与深度理解)
  • 禁用 IPython 历史记录 history.sqlite
  • Luogu P7914 [CSP-S 2021] 括号序列 题解 [ 蓝 ] [ 区间 DP ] [ 前缀和优化 ] [ 调试技巧 ]
  • 扩展BaseMapper类 - 详解
  • 《程序员修炼之道:从小工到专家》前五分之二观后感
  • 矩阵快速幂章节笔记(这里主要介绍的是我的错题)
  • 实验二 现代C++编程初体验
  • P5322 [BJOI2019] 排兵布阵
  • 题解:P9292 [ROI 2018] Robomarathon
  • [题解]P5322 [BJOI2019] 排兵布阵
  • 考前打印
  • 申威服务器安装Nacos 2.0.3 RPM包详细步骤(Kylin V10 sw_64架构)​附安装包
  • ZKY精选冲刺省选国赛仿真训练题
  • MySQL 查询与更新语句执行过程深度解析:从原理到实践​ - 指南
  • ZKY精选冲刺省选国赛技巧训练题
  • 逆向基础--编码(001)
  • 20251027 - 倍增 ST表
  • 周康阳精选冲刺省选国赛思维训练题
  • Luogu P7913 [CSP-S 2021] 廊桥分配 题解 [ 绿 ] [ 贪心 ] [ 前缀和 ] [ STL ]