本部分总题单如下
【腾讯文档】副本-CSP-JS+NOI 题单 (未完待续)
https://docs.qq.com/sheet/DSmJuVXR4RUNVWWhW?tab=BB08J2
https://www.luogu.com.cn/problem/P2866
农夫约翰有 N 头奶牛正在过乱头发节。
每一头牛都站在同一排面朝右,它们被从左到右依次编号为 1, 2, \cdots, N 。编号为 i 的牛身高为 h_i 。第 N 头牛在最前面,而第 1 头牛在最后面。
对于第 i 头牛前面的第 j 头牛,如果 h_i>h_{i+1}, h_i>h_{i+2}, \cdots, h_i>h_j ,那么认为第 i 头牛可以看到第 i+1 到第 j 头牛。
定义 C_i 为第 i 头牛所能看到的牛的数量。请帮助农夫约翰求出 C _ 1 + C _ 2 + \cdots + C _ N 。
输入共 N + 1 行。
第一行为一个整数 N ,代表牛的个数。
接下来 N 行,每行一个整数 a _ i ,分别代表第 1, 2, \cdots, N 头牛的身高。
输出共一行一个整数,代表 C _ 1 + C _ 2 + \cdots + C _ N 。
6
10
3
7
4
12
2
5
对于 100\% 的数据,保证 1 \leq N \leq 8 \times 10 ^ 4 ,1 \leq h _ i \leq 10 ^ 9 。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 8e4 + 10; // 最多 80000 头牛
int n, ans;
int h[maxn]; // 存储每头牛的身高
int main() {
// 输入牛的数量
cin >> n;
// 输入每头牛的身高,h[1] 是第一头牛,h[n] 是最后一头牛
for (int i = 1; i <= n; ++i) {
cin >> h[i];
}
// 对于每一头牛 i,从它右边开始找连续比它矮的牛
for (int i = 1; i <= n - 1; ++i) {
int count = 0; // 当前牛能看到的牛的数量
for (int j = i + 1; j <= n; ++j) {
if (h[i] > h[j]) {
count++;
} else {
break; // 一旦遇到不比它矮的,后面就看不到了
}
}
ans += count;
}
// 输出总和
cout << ans << endl;
return 0;
}
当然可以!下面是你提供的代码,我将为它添加完整详细的注释,帮助你理解它的每一步操作。
这道题要求我们计算每一头牛能看到的“右侧连续比它矮”的牛的数量之和。
使用 单调栈(递减栈) 可以高效地解决这个问题。
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
// 常量定义(虽然没有用到 M 和 MOD,但可能是模板代码)
constexpr int N = 8e4, MAX_N = N + 10;
int n; // 牛的数量
int height; // 用于存储当前牛的身高
ll ans = 0; // 答案变量,记录所有牛能看到的总数
// 函数:禁用 C++ 的同步流,加快输入输出速度
void disable_sync()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
}
stack<int> cows; // 单调栈:保存的是当前牛右边的、可能被看到的牛的身高(保持栈是递减的)
int main()
{
// 禁用同步流,提高读写效率
disable_sync();
// 输入牛的数量
cin >> n;
// 从左到右依次读入每头牛的身高
for (int i = 1; i <= n; ++i)
{
cin >> height;
// 当前牛的身高 >= 栈顶元素时,说明栈顶的牛会被当前牛挡住
// 所以它们不可能再被更左边的牛看到,因此弹出
while (!cows.empty() && height >= cows.top())
{
cows.pop();
}
// 此时栈中剩下的都是比当前牛高的,所以当前牛可以看到这些牛
ans += cows.size();
// 把当前牛压入栈中,供后续更左边的牛判断使用
cows.push(height);
}
// 输出最终的答案
cout << ans << endl;
return 0;
}
6
10
3
7
4
12
2
当前牛身高 | 栈状态(栈底 → 栈顶) | 能看到的牛数 | 累计 ans |
---|---|---|---|
10 | 10 | 0 | 0 |
3 | 10, 3 | 1 | 1 |
7 | 10, 7 | 1 | 2 |
4 | 10, 7, 4 | 2 | 4 |
12 | 12 | 0 | 4 |
2 | 12, 2 | 1 | 5 |
✅ 最终输出 ans = 5
,与题目样例一致。
如果你还想了解这个算法背后的原理,或者想练习类似题目(如“可见山峰对”、“直方图最大矩形”等),我可以继续为你提供讲解。是否需要?
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 删除。