Pinely Round 5 (Div. 1 + Div. 2) A-D细解

news/2025/11/10 17:35:28/文章来源:https://www.cnblogs.com/autumnmist/p/19200593

Pinely Round 5 (Div. 1 + Div. 2)

A. Round Trip

【题目】
参加cf比赛,分两类div1 div2, div1对所有人rated, div2只对<X的rated。
你可以主动选择在rated的场次加分或者减分,如果当前场次能够rated,当前分为R,则变动后区间为[R-D,R+D],即加减D。
输入一个有1和2组成的字符串,表示参赛顺序
输出最多能参加多少场【rated】的场次。

【题解】
显然分越低 越可能触发rated,所以一直掉分就是了。
【代码】

void solve() {int R0, X, D, n; cin >> R0 >> X >> D >> n;string s; cin >> s;int ans = 0;for (auto c : s) {if (c == '1' || c == '2' && R0 < X) {R0 = max(0, R0 - D);ans++;}}cout << ans << endl;
}

B. Make Connected
【题目】
给定n*n的矩阵,每个格子初始可能是黑色或者白色。你可以操作任意次【把白格子改为黑格子】
要求最后满足如下两个条件:

  • 最终所有黑格子都是连通的
  • 任意横向或者纵向不能有三个连续的黑格子。

【题解】
要想让某个格子连向另外的格子可以怎么走?
假设第一次向右,显然下一次必然不能向右,否则会有连续三个横向。
比如
##
所以第二次只能向上或者向下,不妨假设是向下
比如
##
.#
第三次显然不能继续向下 否则会有连续三个纵向
所以要么向左 要么向右
注意这里需要分类
如果向左会形成
##
##
此时再也无法移动
这就是【情况1,矩阵中存在一个唯一的2*2方格】
如果向右会形成
##.
.##
注意后续是循环右下 且无法选择别的方向。
这是【情况2,矩阵中所有黑色块被一个锯齿形覆盖】
注意这个锯齿形的方向可能是正反对角线,更细一点可能是先右再下或者先下再右。
根据这个思路可以直接模拟移动来处理。实际代码我们可以更聪明一点。

  • 关于方块的判定
//这个是完全独立的判定
//注意先判断总的黑块必须是四个
for (int i = 0; i < n - 1; i++) {for (int j = 0; j < n - 1; j++) {if (grid[i][j] == '#' && grid[i][j + 1] == '#' &&grid[i + 1][j] == '#' && grid[i + 1][j + 1] == '#') {cout << "YES" << endl;return;}}
}

另一种判定方式取得所有#位置的i,j各自的最大值和最小值,显然应当有
\(max_i-min_i==1\) && \(max_j-min_j==1\)

  • 关于Z字形判定
    一个基础知识,如何判定是否在对角线上?
    以左上角到右下角的对角线为例
    设所有坐标为\(x_i\) \(y_i\)
    必然有\(x_i-y_i=0\)
    如果这条对角线向右偏移一格呢?
    比如
    .#..
    ..#.
    ...#
    ....
    显然满足\(x_i-y_i=-1\)
    所以不论偏移多少的对角线
    只要在对角线上应当满足\(d=x_i-y_i\)是同一个值
    所谓的z字形,就是两条相邻的斜线
    则必然有所有坐标的【差值的差值】为0或者1
    比如某个黑块坐标差值为3,则另一个坐标差值必须是2,3或者4
    注意 还有反对角线
    反对角线易知满足\(x_i+y_i=d\),其它条件相同。
    两种对角线满足一种即可。

【代码】

void solve() {int n; cin >> n;vector<string> grid(n);for (int i = 0; i < n; i++) cin >> grid[i];int cnt = 0;for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if (grid[i][j] == '#') {cnt++;}}}//如果只有四个并且形成一个方块是可以的if (cnt == 4) {for (int i = 0; i < n - 1; i++) {for (int j = 0; j < n - 1; j++) {if (grid[i][j] == '#' && grid[i][j + 1] == '#' &&grid[i + 1][j] == '#' && grid[i + 1][j + 1] == '#') {cout << "YES" << endl;return;}}}}//检测对角线相邻int mind1 = INT_MAX, mind2 = INT_MAX, maxd1 = INT_MIN, maxd2 = INT_MIN;for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if (grid[i][j] == '#') {mind1 = min(mind1, j - i);mind2 = min(mind2, i + j);maxd1 = max(maxd1, j - i);maxd2 = max(maxd2, i + j);}}}if (maxd1 - mind1 <= 1 || maxd2 - mind2 <= 1) {cout << "YES" << endl;}else cout << "NO" << endl;
}

C. Loyalty

【题目】
给定一个模数X
给定一组商品价格为\(a_i\)\(a_i<=X\)
你每买一个商品,累积消费和设为S,每当S/X增加时会得到当前的这个商品价格的忠诚值。
任意选择购买顺序,输出最大忠诚值。
比如[2,3] X=4 初始S/X=0,购买第二个商品时会导致S/X=5/4>0
此时选择第二次买价格为3的商品可以获得最大忠诚度3
【题解】
这个似乎比B要简单。
模型也比较简单了,显然需要再每次升级的最后一次要买当前剩余价格最大的。
简单排序数组,从0开始枚举i,同时维护末尾元素last
如果当前累计和\(S+a_{last}\)会升级,则安排last元素,同时last--
直到所有元素添加进去即可

【代码】

using i64 = long long;
void solve() {i64 n, x; cin >> n >> x;vector<i64> nums(n);for (int i = 0; i < n; i++) cin >> nums[i];sort(nums.begin(), nums.end());vector<i64> vec;i64 sum = 0;int L = 0, R = n - 1;i64 ans = 0;while (vec.size() < n) {i64 v = nums[R];if ((sum + v) / x > sum / x) {vec.push_back(v);sum += v;ans += v;R--;}else {vec.push_back(nums[L]);sum += nums[L];L++;}}cout << ans << endl;for (int i = 0; i < n; i++) cout << vec[i] << " ";cout << endl;
}

D. Locked Out
【题目】
给定长为n的数组nums,1<=nums[i]<=n
一次操作中 可以移除任意一个元素。
要求最终数组中 不存在任意的i<j,且nums[j]-nums[i]=1
也就是不能存在任何一个元素比它前面出现的某个元素恰好大1
[1,2,3,4,5]可以删减为[1,3,5]
[5,4,3,2,1]不需要删减

【题解1】
一道很好的题目。有很多技巧可以学。
不限制复杂度 能有什么思路?
差值为1启发我们按值排序dp
每个值可能有多个,但是总数是n

trick:按值分类,哈希套列表的形式是避免复杂度上升的处理办法。
此处由于值域固定<=n 所以可以直接列表套列表

trick:另一种可以把值和下标合并处理,形成一个单列表,每个元素为二元值。

trick:题目询问最少移除多少个,要能立即意识可以转换为最多保留多少个
也就是正难则反,并且最多保留个数非常类似于上升子序列之类的经典思想。

dp[x][i]定义为从小到大枚举到x的第i个下标,并选择x时【最多】可以保留的元素个数
现在考虑转移来源:
假设枚举到某个值x,由于是列表,假设枚举到的这个x位于原数组位置p。
那么dp[x]i可能从哪里转移

  • 可能是dp[y] (y <= x - 2)的任意位置,显然我们需要取最大值。
    因为只限制了不允许x - y = 1,这个来源是显然的。比如[1,3]这种
  • 可能是dp[y][j] (y = x - 1, 这里j表示第j个y,其下标设为q,则必须有q > p)
    也就是虽然y = x - 1 但是y位于x后面。比如[3,2]这种形式
  • 可能是dp[x][j] (且这个x(第j个x)的下标q > p)
    比较难理解的点,显然一个靠后的x对应的个数已知,则更靠前的x必然合法
    比如[1,2,1,2],如果选择了第二个2,则必然前方不存在1,故前面的2自然可行。
    反之不能成立。
    这同时也启发我们枚举同一个值的不同位置时 要【倒序】枚举。
    也就是dp[x][i]第一维的x从1-n枚举,对于每个x,其下标列表要是倒序的。

对于来源1,朴素的做法,可以用个数组mx,mx[i]表示枚举到值i时的最大值
这样取值和设值都比较方便。
对于来源2,抽象一下模型,每轮需要设置y在某个下标q下的值
而查询时,需要找到所有[p,n]范围内的最大值。显然这是个树状数组或者线段树模型
注意可以不单独查询y=x-1的值的下标,实际上可以直接查询所有值的[q,n]下标的最大值即可。
因为跟来源1或者3是重合的。
如果不用线段树,即在y=x-1的所有y下标中查找>p的那部分的最大值。
考虑到我们本来就是从大到小枚举的,实际这个值是一个【前缀最大值】
因此可以在维护时记录premax,然后用双指针或者二分去找到对应的值。
对于来源3,可以简单记录当前相同值的一系列下标下最大值即可

trick:如果来源1的值只用一个值表示呢?有个延迟更新的技巧
设mx表示全局最大值,premx表示前缀最大值
则每一轮可以这样,伪代码如下
假设从1开始枚举,此时枚举到4,mx存储的是到2的最大值,premx存储到3的最大值。

int tmp = premx; //先取出之前最大值(到2的) 用于计算,后续只使用tmp
premx = max(premx, curmx); //之后直接把最大值用上一轮的当前最大更新(即之前最大值变成了到3的)
curmx = max(curmx, XXXX); //更新当前最大值(变成到4的)

下一轮枚举到5,显然有存储最大值为3

【代码】
这里使用了二分查找 而不是线段树

#include <bits/stdc++.h>
using namespace std;
void solve() {int n; cin >> n;vector<vector<int>> all(n + 1);for (int i = 0; i < n; i++) {int v; cin >> v;all[v].push_back(i);}for(int v = 1; v <= n; v++) sort(all[v].begin(), all[v].end(), greater<int>());int preMax = 0;int curMax = 0;vector<vector<int>> pre(n + 1);for (int v = 1; v <= n; v++) {pre[v].resize(all[v].size());int tmp = preMax;preMax = max(preMax, curMax);for (int i = 0; i < all[v].size(); i++) {int p = all[v][i];int leftMx = 0;if (all[v - 1].size() > 0) {int low = 0, high = all[v - 1].size() - 1;while (low <= high) {int mid = low + (high - low) / 2;if (all[v - 1][mid] < p) high = mid - 1;else low = mid + 1;}if (high >= 0) pre[v][i] = pre[v - 1][high] + 1;}if (i == 0) pre[v][i] = max(pre[v][i], tmp + 1);else {pre[v][i] = max({ pre[v][i], tmp + 1, pre[v][i - 1] + 1 });}curMax = max(curMax, pre[v][i]);}}cout << n - curMax << endl;
}
int main() {ios::sync_with_stdio(false);int t; cin >> t;while (t-- > 0) solve();
}

【题解2】
先介绍个东西叫做slope trick
而本题有一个非常类似slope trick思想的【贪心】做法

【代码】

void solve() {int n; cin >> n;vector<vector<int>> all(n + 1);for (int i = 0; i < n; i++) {int v; cin >> v;all[v].push_back(i);}int ans = 0;for (int i = 1; i < n; i++) {if (all[i].size() == 0 || all[i + 1].size() == 0) continue;int L = all[i].size() - 1;int R = all[i + 1].size() - 1;while (L >= 0 && R >= 0) {if (all[i][L] < all[i + 1][R]) {ans++;all[i + 1].pop_back();L--;R--;}else L--;}}cout << ans << endl;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/961600.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年三相滤波器源头厂家权威推荐榜单:EMI电源滤波器/防雷滤波器/电源滤波器源头厂家精选

在工业自动化与电能质量要求不断提升的背景下,三相滤波器作为抑制电磁干扰、保障设备稳定运行的关键元件,其性能直接影响整个电力系统的可靠性。根据行业数据显示,全球电源滤波器市场规模预计到2027年将达到13.6亿美…

UT010029: Stream is closed

做下载文件的时候遇到了一个报错:UT010029: Stream is closed经排查,是因为下载接口有返回值导致的

官宣上线!RocketMQ for AI:企业级 AI 应用异步通信首选方案

随着 AI 技术的快速发展和应用落地,RocketMQ 已完成向“AI MQ”方向的战略升级,不仅支持传统的微服务应用,也致力于为企业级 AI 应用的开发和集成提供一站式异步通信解决方案,涵盖会话管理、Agent 通信、知识库构建…

GD32VW553-IOT V2 测评和移植 - 实践

GD32VW553-IOT V2 测评和移植 - 实践pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monac…

什么是 FFmpeg:开源免费的多媒体处理框架 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

AI元人文宪章:在缺陷中前行——价值权衡时代的协作体系

AI元人文宪章:在缺陷中前行——价值权衡时代的协作体系 前言:拥抱不完美的规则 规则,是人类智慧的结晶,也是人类无知的映射。我们制定规则以求秩序与公平,却必须清醒地认识到:任何规则体系,从其诞生之初便内嵌了…

2025年台湾铨盛仪表公司口碑推荐榜

2025年台湾铨盛仪表公司口碑推荐榜专业推荐首选:昆山凯沃自动化控制设备有限公司作为台湾铨盛仪表(ADTEK)在中国大陆地区授权一级代理商已达18年的专业服务商,昆山凯沃自动化控制设备有限公司凭借其深厚的技术底蕴…

2025年销量高的前置过滤器口碑推荐榜

2025年销量高的前置过滤器口碑推荐榜随着人们对饮用水安全的日益重视,前置过滤器作为家庭净水系统的第一道防线,已成为越来越多家庭的必备选择。在众多品牌中,GOOTHO库硕凭借其卓越的性能和贴心的定制服务,在2025年…

2025年靠谱的藤椒火锅底料口碑推荐榜单

2025年藤椒火锅底料口碑推荐榜单:饭巢藤椒火锅底料领跑行业榜单前言随着消费者对健康饮食需求的不断提升,藤椒火锅底料凭借其清爽麻香、不油腻的特点,成为2025年火锅市场的新宠。经过对全国3000余家商超专柜销售数据…

2025年离心管道风机定制厂家推荐排行榜

2025年离心管道风机定制厂家推荐排行榜在工业通风和空调系统领域,离心管道风机作为核心设备,其性能和质量直接影响整个系统的运行效率。随着2025年的到来,市场对高品质离心管道风机的需求持续增长。以下是经过综合评…

CF2119E And Constraint

学到了一些东西。 首先考虑到 \(b_i\) 的二进制位一定包含了 \(a_{i - 1} | a_i\) 的二进制位,我们不妨求一个 \(p_i\) 表示将 \(b_i\) 最少加多少可以满足这个条件的数。 但是我们发现可能存在一些的与的数比 \(a_i\…

Follow the Penguins

题意: 给定若干个点,它们有一个要追赶的点和当前位置,求最后所有点停止的时间,(一个点移动的速度为0.5) 思路: 使用set模拟优先队列 求出每个点移动的方向(一定不变了) 存一个pair<当前点和追赶点的距离 即…

2025年钢管输送翻转生产厂家权威推荐榜单:车床辅助机构/油套管加工机构/管螺纹加工送料机构源头厂家精选

在工业自动化与油气产业协同发展的背景下,钢管输送翻转设备作为管材加工产线的核心装备,其性能直接影响生产效率和产品质量。根据行业数据显示,全球工业自动化设备市场规模预计到2027年将达到3062亿美元,年复合增长…

zed odoo lsp配置

文档: https://github.com/odoo/odoo-zed https://github.com/odoo/odoo-ls/wiki/3.-Configuration-files#no-configuration-file // zed settings.json"lsp": {"rust-analyzer": {"initial…

Raylib 音乐和音效

音乐和音效 相关函数: void InitAudioDevice(void); void CloseAudioDevice(void); Music LoadMusicStream(const char *fileName); void PlayMusicStream(Music music); void UpdateMusicStream(Music music); void S…

2025年挤压铝型材推荐榜单

2025年挤压铝型材推荐榜单:铝原素领跑行业创新随着工业制造技术的快速发展,挤压铝型材在各行各业的应用日益广泛。作为铝型材定制领域的专业制造商,铝原素凭借其卓越的产品质量和全方位的服务优势,在2025年挤压铝型…

oh-my-zsh又双叒叕出问题了......

如下图,本来提示符中是没有那个 ‹master*› 的,看着闹心,先记录一下,去掉了之后再给出解决方案。

读书笔记:并行 DML:批量数据修改的“超级加速器”

我们的文章会在微信公众号IT民工的龙马人生和博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢! 由于博客中有大量代码,通过页面浏览效果更佳。本文为个人学…

2025年镀锌钢格板品牌推荐排行榜单

2025年镀锌钢格板品牌推荐排行榜单前言随着工业建设的快速发展,镀锌钢格板作为重要的建筑材料,在各行各业中发挥着不可替代的作用。2025年,随着技术的不断进步和市场的日益成熟,镀锌钢格板行业也呈现出新的发展态势…

高端UI设计公司的“审美模型”:如何让界面更有记忆点?

高端UI设计公司的“审美模型”:如何让界面更有记忆点?在 UI 设计同质化严重的当下,“好看” 已不再是高端界面的核心竞争力,“有记忆点” 才是 —— 用户可能会忘记某款产品的功能细节,却会对 “独特的视觉感受、…