本部分总题单如下
【腾讯文档】副本-CSP-JS+NOI 题单 (未完待续)
https://docs.qq.com/sheet/DSmJuVXR4RUNVWWhW?tab=BB08J2
https://www.luogu.com.cn/problem/P1901
某地有 个能量发射站排成一行,每个发射站 都有不相同的高度 ,并能向两边(两端的发射站只能向一边)同时发射能量值为 的能量,发出的能量只被两边最近的且比它高的发射站接收。显然,每个发射站发来的能量有可能被 或 或 个其他发射站所接受。
请计算出接收最多能量的发射站接收的能量是多少。
第 行一个整数 。
第 到 行,第 行有两个整数 和 ,表示第 个发射站的高度和发射的能量值。
输出仅一行,表示接收最多能量的发射站接收到的能量值。答案不超过 32 位带符号整数的表示范围。
3
4 2
3 5
6 10
7
对于 的数据, 。
对于 的数据, 。
对于 的数据, 。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int n;
int h[maxn],v[maxn],s[maxn];
int main(){
// cout<<maxn<<endl;
// 输入n 表示n个发射塔
cin>>n;
// 输入n行 每行h高度 和 v能量
for(int i=1;i<=n;i++){
cin>>h[i]>>v[i];
}
// 每次都寻找左右两遍第1个比当前塔高度的大的,加上能量
for(int i=1;i<=n;i++){
// 循环内要完成的事情 是 朝着两遍发射 然后接受
if(i==1){
// 只朝右发射
for(int j=i+1;j<=n;j++){
if(h[j]>h[i]) {
s[j]+=v[i];
break;
}
}
}else if(i==n){
// 只朝左发射
for(int j=i-1;j>=1;j--){
if(h[j]>h[i]) {
s[j]+=v[i];
break;
}
}
}else{
// 朝右发射
for(int j=i+1;j<=n;j++){
if(h[j]>h[i]) {
s[j]+=v[i];
break;
}
}
// 朝左发射
for(int j=i-1;j>=1;j--){
if(h[j]>h[i]) {
s[j]+=v[i];
break;
}
}
}
}
// for(int i=1;i<=n;i++){
// cout<<h[i]<<v[i]<<" ";
// }
int t=s[1];
for(int i=1;i<=n;i++){
if(t<s[i]) t=s[i];
}
cout<<t;
return 0;
}
/*
3
4 2
3 5
6 10
7
*/
现在使用单调栈的技巧来解决这个问题,目的是高效地找到每个发射站左右两边第一个比它高的发射站。
#include<iostream>
using namespace std;
const int maxn = 1e6 + 10; // 定义最大数组大小,支持最多1e6个发射站
// sum[i] 表示第i个发射站接收到的能量总和
int s1[maxn], h[maxn], v[maxn], sum[maxn], ans, n, top;
int main() {
cin >> n;
// 输入每个发射站的高度h[i]和能量值v[i]
for(int i = 1; i <= n; i++) {
cin >> h[i] >> v[i];
// 单调栈处理:从栈顶弹出所有比当前发射站矮的发射站
// 这些被弹出的发射站会把它们的能量v[s1[top]]传给当前发射站i
while(top && h[s1[top]] < h[i]) {
sum[i] += v[s1[top]]; // 当前发射站i接收来自这些发射站的能量
top--; // 弹出栈顶
}
// 如果栈中还有元素(即存在未被处理的发射站)
// 那么当前发射站i的能量v[i]会被传递给它左边第一个更高的发射站
if (top > 0) {
sum[s1[top]] += v[i]; // 栈顶发射站接收当前发射站i发出的能量
}
s1[++top] = i; // 将当前发射站i压入栈中
}
// 遍历所有发射站,找出接收能量最多的那个
for(int i = 1; i <= n; i++) {
ans = max(ans, sum[i]);
}
// 输出最终结果
cout << ans << endl;
return 0;
}
/*
3
4 2
3 5
6 10
7
*/
下面是对这段代码的工作原理和逻辑的解释:
maxn
:定义了一个常量表示数组的最大大小。s1[maxn]
:这是一个栈,用来存储发射站的索引,用于寻找最近的比当前发射站高的发射站。h[maxn]
, v[maxn]
:分别存储每个发射站的高度和能量值。sum[maxn]
:存储每个发射站接收到的能量总和。ans
:记录接收最多能量的发射站所接收的能量值。n
:发射站的数量。top
:栈顶指针,初始化为0。n
。h[i]
和能量值 v[i]
。i
,使用一个 while
循环检查栈顶元素(即之前遇到的发射站),如果栈顶发射站的高度小于当前发射站的高度,则从栈中弹出,并将该发射站的能量值累加到当前发射站的接收能量中。sum
数组,找出接收能量最大的值,并将其赋值给 ans
。s1
),可以在O(n)的时间复杂度内找到每个发射站左右两边第一个比它高的发射站。这是因为每次新发射站加入时,都会“清理”掉那些比它矮的旧发射站,确保栈中的发射站高度总是递减的。虽然你的实现基本正确,但有一个小问题需要注意:在更新 sum[s1[top]]+=v[i];
这行代码时,可能会尝试访问无效的栈顶元素(比如当栈为空时)。为了避免潜在的错误,可以考虑在这个操作之前添加一个条件判断 if(top > 0)
来确保栈不为空。此外,为了使代码更加清晰,可以考虑增加一些注释来解释每一步的目的。
https://cspoj.com/contest.php?cid=1002Fus5yz4x3EcSJH1Z
注意事项
文件名(程序名和输入输出文件名)必须使用英文小写。(提交必须使用freopen()进行提交)
C/C++ 中函数 main() 的返回值类型必须是 int,程序正常结束时的返回值必须是0。
提交的程序代码文件的放置位置请参考各省的具体要求。
因违反以上三点而出现的错误或问题,申述时一律不予受理。
若无特殊说明,结果的比较方式为全文比较(过滤行末空格及文末回车)。
程序可使用的栈空间内存限制与题目的内存限制一致。
全国统一评测时采用的机器配置为:Inter® Core™ i7-8700K CPU @3.70GHz,内存 32GB。上述时限以此配置为准。
只提供 Linux 格式附加样例文件。
评测在当前最新公布的 NOI Linux 下进行,各语言的编译器版本以此为准
假设输入样例数据存在文件test.in中,输出样例数据存在文件test.out中,
则在CSP、NOI等比赛的代码中,需添加freopen、fclose语句,
内容详见模板代码如下。
#include <bits/stdc++.h>
#include<cstdio>//必须包含cstdio头文件
#include<iostream>
using namespace std;
int main(){
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
cout<<"Hello NOI"<<endl;
fclose(stdin);
fclose(stdout);
return 0;
}
复制
下面为函数的简介,详细可参见 http://www.cplusplus.com/reference/clibrary/cstdio/freopen.html
函数名:freopen
声明:
FILE _freopen( const char_ path, const char _mode, FILE_ stream );
所在文件: stdio.h
参数说明:
path: 文件名,用于存储输入输出的自定义文件名。
mode: 文件打开的模式。和fopen中的模式(如r-只读, w-写)相同。
stream: 一个文件,通常使用标准流文件。
返回值:成功,则返回一个path所指定文件的指针;失败,返回NULL。(一般可以不使用它的返回值)
功能:实现重定向,把预定义的标准流文件定向到由path指定的文件中。标准流文件具体是指stdin、stdout和stderr。其中stdin是标准输入流,默认为键盘;stdout是标准输出流,默认为屏幕;stderr是标准错误流,一般把屏幕设为默认。通过调用freopen,就可以修改标准流文件的默认值,实现重定向。
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
freopen("7532.in", "r", stdin);
freopen("7532.out", "w", stdout);
//原来的代码保持不变
double a, b, r;
int k;
cin >> a >> b;
k = int(a/b);
r = a - b * k;
printf("%g", r);
//-------------
fclose(stdin);
fclose(stdout);
return 0;
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有