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();
}
}