C. Building a Fence(范围判定)

Problem - 1469C - Codeforces

你想建造一个由n个相等部分组成的栅栏。所有部分的宽度都等于1,高度都等于k。

不幸的是,篱笆下面的地面并不平坦。为了简单起见,你可以认为第i节下面的地面等于hi。

你应该遵循几个规则来建造围栏。

连续的部分应该有一个共同的边,长度至少为1。
第一节和最后一节应该站在相应的地面上。
中间的部分可以在地面上,也可以更高,但不能高于地面上的k-1(高度应该是整数)。
第一个测试案例中可能的栅栏之一(蓝色)。
是否有可能建造一个符合所有规则的围栏?

输入
第一行包含一个整数t(1≤t≤104)--测试案例的数量。

每个测试用例的第一行包含两个整数n和k(2≤n≤2⋅105;2≤k≤108)--栅栏的段数和每个段的高度。

每个测试案例的第二行包含n个整数h1,h2,...,hn(0≤hi≤108),其中hi是第i段下面的地面高度。

保证测试案例的n之和不超过2⋅105。

输出
对于每个测试案例,如果有可能建立符合所有规则的围栏,则打印YES。否则,打印NO。

你可以在任何情况下打印每个字母(例如,YES,Yes,yes,yEs都将被识别为肯定答案)。

例子
输入复制
3
6 3
0 0 2 5 1 1
2 3
0 2
3 2
3 0 2
输出拷贝

是的

注意
在第一个测试案例中,可能的围栏之一在图片中显示。

在第二个测试案例中,根据第二条规则,你应该在相应的地面上建造两个部分,由于k=3,h1=0,h2=2,所以第一条规则也得到了满足。

在第三个测试案例中,根据第二条规则,你应该把第一部分建在高度3上,第三部分建在高度2上。根据第一条规则,第二节应该至少在高度为2的地方(与第一节有一个共同的边),但是根据第三条规则,第二节最多可以建在高度为h2+k-1=1的地方。

题解:

我们维护一个范围l ~ r

l = max(l - k + 1,a[i])代表l可以是当前l往下k - 1格,但是肯定要大于等于地面

r = min(r + k -1,a[i] + k - 1),代表r可以是当前r往上k - 1格,但是肯定要小于等于当前地面往上k-1格

如果途中l > r说明肯定不成立,或者最后,a[i]不在l~r内也不成立

#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<cstring>
#include<cmath>
#include<set>
using namespace std;
#define int long long
int h[200050];
void solve()
{
	int n,k;
	cin >> n >> k;
	for(int i = 1;i <= n;i++)
	cin >> h[i];
	int l = h[1],r = h[1];
	int f = 1;
	for(int i = 2;i <= n;i++)
	{
		l = max(l - k + 1,h[i]);
		r = min(r + k -1,h[i]+k - 1);
		if(l > r)
		{
			f = 0;
			break;
		}
	}
	if(h[n] < l||h[n] > r)
	f= 0;
	if(f)
	cout <<"YES\n";
	else
	cout <<"NO\n";
}
//5 2
//
signed main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);
//	cout.tie(0);
	int t = 1;
	cin >> t;
    while(t--)
	{

		solve();
	} 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值