Interesting Subarray 解题报告

题目链接:https://codeforces.com/contest/1270/problem/B

For an array a a a of integers let’s denote its maximal element as max ⁡ ( a ) \operatorname{max}(a) max(a), and minimal as min ⁡ ( a ) \operatorname{min}(a) min(a). We will call an array a a a of k k k integers interesting if max ⁡ ( a ) − min ⁡ ( a ) ≥ k \operatorname{max}(a)−\operatorname{min}(a)≥k max(a)min(a)k. For example, array [ 1 , 3 , 4 , 3 ] [1,3,4,3] [1,3,4,3] isn’t interesting as max ⁡ ( a ) − min ⁡ ( a ) = 4 − 1 = 3 < 4 \operatorname{max}(a)−\operatorname{min}(a)=4−1=3<4 max(a)min(a)=41=3<4 while array [ 7 , 3 , 0 , 4 , 3 ] [7,3,0,4,3] [7,3,0,4,3] is as max ⁡ ( a ) − min ⁡ ( a ) = 7 − 0 = 7 ≥ 5 \operatorname{max}(a)−\operatorname{min}(a)=7−0=7≥5 max(a)min(a)=70=75.

You are given an array a a a of n n n integers. Find some interesting nonempty subarray of a a a, or tell that it doesn’t exist.An array b b b is a subarray of an array a a a if b b b can be obtained from a a a by deletion of several (possibly, zero or all) elements from the beginning and several (possibly, zero or all) elements from the end. In particular, an array is a subarray of itself.

题目大意:

找出一个数列有趣的连续子序列,有趣的定义为序列的最大值减去最小值大于等于序列的长度;如果存在这样有趣的连续子序列,输出“YES”并输出任意一个,否则输出“NO”。

题解:

根据贪心的思想,如果一个有趣的序列,它的最大最小值不在两端点,那么其以最大最小值组成的序列也必定是有趣的。因此我们可能会想:能不能理解为寻找 ∣ a [ r ] − a [ l ] ∣ ≥ r − l + 1 |a[r]-a[l]|\geq r-l+1 a[r]a[l]rl+1呢?

当时我陷入了这个坑纠结了很久,我试图移项得出 ( a [ r ] − r ) − ( a [ l ] − l ) ≥ 1 (a[r]-r)-(a[l]-l)\geq 1 (a[r]r)(a[l]l)1,然后寻找 a [ i ] − i a[i]-i a[i]i的最大值与最小值进行相减来判断。但实际上因为绝对值的存在,这样子并不能行得通。

正确的思路是比较任意相邻两个数即可。首先,如果存在相邻两个数的绝对值之差大于 1 1 1,那么它们组成的序列即是有趣的;而如果任意相邻两个数的绝对值之差都小于等于 1 1 1,那么不管如何取连续子序列,显然每增加一个数,右边的 k k k会加 1 1 1,而左边增加值小于等于 1 1 1,仍然不是有趣的序列。

总的来说,这道题乍一看不太好下手,但是结论却非常简单。

代码:

#include<cstdio>
#include<algorithm>
using namespace std;
 	int t,n;
 	int a[200001];
int main()
{
 	scanf("%d",&t);
 	while (t --)
 	{
  		scanf("%d",&n);
  		for (int i = 1;i <= n;i ++)
   			scanf("%d",&a[i]);
  		bool flag = false;
  		for (int i = 2;i <= n;i ++)
   			if (abs(a[i] - a[i - 1]) > 1)
   			{
    				flag = true;
    				printf("YES\n");
    				printf("%d %d\n",i - 1,i);
    				break;
   			}
  		if (!flag)
   			printf("NO\n");
 	}
 	return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值