P6181 [USACO10OPEN]Mountain Watching S 题解
题意:
- 给定 \(n\) 和 \(n\) 个数,求最宽的山的宽度(其实就是最长单峰子序列,
但我不会)。
数据范围:
$ 1 \leq n \leq 10^5 , 1 \leq h_i \leq 10^9 $
做法:
-
注意:直接爆搜会超时!!!
-
建数组 \(h\) 存放山脉信息,最大值
maxn存最宽山的宽度; -
每次从 \(i\) 开始搜索,定义 \(l\) 和 \(r\) , \(l\) 记录向左搜到的位置,\(r\) 记录向右搜到的位置(注意搜到边界 \(1\),\(n\) 时的特判),搜索方法题目中给出来了
- 如果现在搜出的山的宽度 \(>\)
maxn则更新maxn;
- 如果现在搜出的山的宽度 \(\leq\)
maxn则不更新maxn;
-
最后输出
maxn。 -
注:三目运算符
表达式1?表达式2:表达式3,若表达式1值为真返回表达式2,否则返回表达式3。
考虑优化:
若某次搜出的山的宽度为 \(n\),那就没有继续搜索下去的必要了,maxn=n,以后再搜出来的山的宽度肯定 \(\leq\) \(n\),就不会再更新 maxn 的值,可以直接跳出循环。不优化最后一个点会TLE。
- 弱化版P1893 山峰暸望可以不优化。
代码
#include<bits/stdc++.h>
using namespace std;
int n,maxn=-1,h[100050];
//maxn存最大值,初始化最小
int ma(int x,int y) { return x>y?x:y; }
//自己写的判断最大值的函数
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>h[i];
for(int i=1;i<=n;i++)
{
int l=i,r=i;
//向左搜索 left,向右搜索 right
while(h[l-1]<=h[l]&&l-1>=1) l--;
while(h[r+1]<=h[r]&&r+1<=n) r++;
maxn=ma(r-l+1,maxn);
//或 maxn=max(r-l+1,maxn);
//自己写函数只是为了加快速度
if(r-l+1==n) break;
//优化:
//不优化会TLE
//若某次搜索出山的宽度为n,
//那这座山的宽度肯定是最大的
//那就没有搜下去的必要了
//直接跳出循环
}
cout<<maxn;
//输出最大值
return 0;
}
以下是博客签名,正文无关
本文来自博客园,作者:Wy_x,转载请在文首注明原文链接:https://www.cnblogs.com/Wy-x/articles/18704619
版权声明:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC-BY-NC-SA 4.0 协议)进行许可。

浙公网安备 33010602011771号