2024/9/15 CSP-S daimayuan模拟赛复盘
2024/9/15 CSP-S daimayuan
A. 达到巅峰
题面描述
Tourist 共参加了
场 codeforces 举办的积分比赛,参加完第 场比赛后,Tourist 的积分被更新为 。我们称第 场比赛结束后,Tourist 的积分「达到巅峰」当且仅当对于所有小于 的正整数 ,都有 。 Tourist 认为他的比赛经历中,越多次比赛结束后他的积分「达到巅峰」,越显得他一直在进步。所以他想把至多一次比赛的积分记录删除,使得他「达到巅峰」的次数尽可能多。
例如,若 Tourist 共参加过
次比赛, 次比赛结束后积分依次为 ,他在第 三场比赛结束后是「达到巅峰」的,但若把第 场比赛的积分记录删除,剩下的四场比赛积分记录为: ,那么每场比赛结束后都「达到巅峰」,故删除第 次记录能使得 Tourist 「达到巅峰」的次数变为最大值。删除任何其他记录都无法使「达到巅峰」次数多达 次。 现在请你帮 Tourist 计算,在至多删除一次比赛的积分记录的情况下,他达到巅峰的次数最多能有几次?
输入 & 输出 & 样例 & 数据范围
输入第一行一个正整数
,代表 Tourist 共参加了几场积分比赛。 接下来一行,有
個正整数 。 输出一个整数表示答案。
对于所有的数据,保证
。
5
1500 1900 1700 1850 2000
4
5
5 2 5 3 5
2
思路解析
可以发现最后删除的那一次的记录肯定在删除前就是一个巅峰,于是我们只用考虑每一个巅峰对答案造成的贡献即可。
这时我们发现对于删除每一个原巅峰后,有可能新成为巅峰的点只可能出现在“当前巅峰和下一个巅峰之间”,同时可能成为新的巅峰的点还得比区间内所有之前的点都大,这样我们就能存下来每两个巅峰之间所有比该区间里之前的值都大的点。
但是如果一个区间内的点想要成为新的巅峰还有一个要求,就是需要比“当前被删除的巅峰的前一个巅峰”还要高,否则依然无法成为巅峰。但是由于我们存下来区间内的点都是有序的,所以可以直接通过二分找到有几个点超过前一个巅峰。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
int n, a[N], top[N], pos[N];
vector<int> v[N];
int main() {
cin >> n;
int mx = 0, s = 0;
for(int i = 1; i <= n; i++) {
cin >> a[i];
if(a[i] > mx) top[i] = ++s, pos[s] = i;
mx = max(mx, a[i]);
}
mx = 0; int cnt = 0;
for(int i = 1; i <= n; i++) {
if(top[i]) mx = 0, cnt++;
else if(a[i] > mx) v[cnt].push_back(a[i]), mx = a[i];
}
int ans = s;
for(int i = 1; i <= s; i++) {
int t = (v[i].end() - upper_bound(v[i].begin(), v[i].end(), a[pos[i - 1]]));
ans = max(ans, s - 1 + t);
}
cout << ans;
return 0;
}
B. 子集数量
题面描述
给你包含
个整数 的多重集 (multiset) ,此多重集有 个子集。 定义一个子集的价值为此子集所有数字的和。
给定
个正整数 ,请输出 中元素数量大于等于 且小于等于 的所有子集中,价值前 大的子集的价值和。
输入 & 输出 & 样例 & 数据范围
输入的第一行包含
个正整数 。 输入的第二行包含
个整数 。 输出一个整数代表答案。
对于所有数据,保证
。
3 2 2 2
2 4 1
11
5 4 3 4
-3 -1 -1 0 3
6
10 234 3 7
524399 920312 697796 866354 762423 574254 790514 483143 926875 290091
1070123901
思路解析
可以发现
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5 + 10;
int n, k, l, r, a[N], s[N];
bool cmp(int x, int y) {return x > y;}
struct node {
int w, x, y, z;
bool operator < (const node &rhs) const {
return rhs.w > w;
}
};
signed main() {
cin >> n >> k >> l >> r;
for(int i = 1; i <= n; i++) cin >> a[i];
sort(a + 1, a + n + 1, cmp);
for(int i = 1; i <= n; i++) s[i] = s[i - 1] + a[i];
priority_queue<node> q;
for(int i = l; i <= r; i++) {
q.push({s[i], i + 1, 0, 0});
}
int ans = 0;
while(k--) {
node u = q.top(); q.pop();
ans += u.w;
if(u.y <= n && u.y > u.z + 1) q.push({u.w + a[u.y] - a[u.y - 1], u.x, u.y - 1, u.z});
if(u.x <= n && u.x > u.y + 1) q.push({u.w + a[u.x] - a[u.x - 1], u.x + 1, u.x - 1, u.y});
}
cout << ans;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人