Nastya and Door(CF1341B)-暴力&前缀和

Nastya and Door

题目链接

Time limit 1000 ms -------- Memory limit 262144 kB

On February 14 Denis decided to give Valentine to Nastya and did not come up with anything better than to draw a huge red heart on the door of the length k (k≥3). Nastya was very confused by this present, so she decided to break the door, throwing it on the mountains.
Mountains are described by a sequence of heights a1,a2,…,an in order from left to right (k≤n). It is guaranteed that neighboring heights are not equal to each other (that is, ai≠ai+1 for all i from 1 to n−1).
Peaks of mountains on the segment [l,r] (from l to r) are called indexes i such that l<i<r, ai−1ai+1. It is worth noting that the boundary indexes l and r for the segment are not peaks. For example, if n=8 and a=[3,1,4,1,5,9,2,6], then the segment [1,8] has only two peaks (with indexes 3 and 6), and there are no peaks on the segment [3,6].
To break the door, Nastya throws it to a segment [l,l+k−1] of consecutive mountains of length k (1≤l≤n−k+1). When the door touches the peaks of the mountains, it breaks into two parts, after that these parts will continue to fall in different halves and also break into pieces when touching the peaks of the mountains, and so on. Formally, the number of parts that the door will break into will be equal to p+1, where p is the number of peaks on the segment [l,l+k−1].
Nastya wants to break it into as many pieces as possible. Help her choose such a segment of mountains [l,l+k−1] that the number of peaks on it is maximum. If there are several optimal segments, Nastya wants to find one for which the value l is minimal.
Formally, you need to choose a segment of mountains [l,l+k−1] that has the maximum number of peaks. Among all such segments, you need to find the segment that has the minimum possible value l.

input

The first line contains an integer t (1≤t≤10^4) — the number of test cases. Then the descriptions of the test cases follow.
The first line of each test case contains two integers n and k (3≤k≤n≤2⋅10^5) — the number of mountains and the length of the door.
The second line of the input data set contains n integers a1,a2,…,an (0≤ai≤10^9, ai≠ai+1) — the heights of mountains.
It is guaranteed that the sum of n over all the test cases will not exceed 2⋅10^5.

output
For each test case, output two integers t and l — the maximum number of parts that the door can split into, and the left border of the segment of length k that the door should be reset to.

Example

Input
5
8 6
1 2 4 1 2 4 1 2
5 3
3 2 3 2 1
10 4
4 3 4 3 2 3 2 1 0 1
15 7
3 7 4 8 2 3 4 5 21 2 3 4 2 1 3
7 5
1 2 3 4 5 6 1
Output
3 2
2 2
2 1
3 1
2 3

题意:
给出一个序列,高度大于左右即为山峰。给定区间长度,求山峰最多且左端点最小的区间。
1、暴力
O(n²)必然超时,故只存下所有山峰的坐标,通过坐标间的距离求给定长度内的山峰个数。eg:可能没有山峰。

擦边过 time:967ms

#include<cstdio>
#include<string.h>
#include<math.h>
using namespace std;
int main ()
{
	int a,b,c,d,t,n,x=0,y=0,z,k,i;
	int s[200102];
	int st[200001];
	scanf("%d",&t) ;
	while(t--)
	{
		scanf("%d%d",&n,&k);
		memset(s,0,sizeof(s));
		memset(st,0,sizeof(st));
		for(a=1;a<=n;a++)
			scanf("%d",&s[a]);
		x=0;
		for(a=2;a<n;a++)
		{
			if(s[a]>s[a-1]&&s[a]>s[a+1])
			{
				st[x++]=a;//存下山峰坐标
			}
		}
		y=0;z=1;
		for(a=0;a<x;a++)
		{
			i=1;
			for(b=a+1;b<x;b++)
			{
				if(st[a]+k-2>st[b])//只要以当时该点的坐标作为左端点,往后的坐标在区间范围内的便是区间内的山峰。
				{
					i++;
				}
				else
					break;
			}
			if(y<i)
			{
				y=i;
				z=st[a+i-1]-k+2;//区域的左端点一定是某个山峰为右端再减去区间长度
			}
		}
		if(z<1)
			z=1;	
		printf("%d %d\n",y+1,z);//结果是求门的碎片,故y+1
	}
	return 0;
} 

2、前缀和
前缀和对于求区间范围数据的处理可提高效率,直接求出任意区间范围内山峰的个数。

#include<cstdio>
#include<string.h>
#include<math.h>
using namespace std;
int main ()
{
	int a,b,c,d,t,n,x=0,y=0,z,k;
	int s[200102];
	int st[200102];
	scanf("%d",&t) ;
	while(t--)
	{
		scanf("%d%d",&n,&k);
		memset(s,0,sizeof(s));
		memset(st,0,sizeof(st));
		for(a=1;a<=n;a++)
			scanf("%d",&s[a]);
		for(a=2;a<n;a++)
		{
			if(s[a]>s[a-1]&&s[a]>s[a+1])
				st[a]=1;
			st[a]+=st[a-1];//边存边处理,又无山峰都要处理
		}
		y=0;z=1;
		for(a=1;a+k-1<=n;a++)
		{
			int i=st[a+k-2]-st[a];//区间内山峰个数
			if(y<i)
			{
				y=i;
				z=a;
			}
		}	
		printf("%d %d\n",y+1,z);
	}
	return 0;
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值