vlambda博客
学习文章列表

一道有顶点的数组题 - 贪心算法


B. Array Sharpening

Let's call it sharpened if and only if there exists an integer 1≤k≤n such that a1<a2<… ak+1>…>an. In particular, any strictly increasing or strictly decreasing array is sharpened. For example:

一个Sharpening数组是指数组的元素最多只有一个顶点,也就是3种类型:升序、降序、先升后降。

The arrays [4], [0,1], [12,10,8] and [3,11,15,9,7,4] are sharpened;
The arrays [2,8,2,8,6,5], [0,1,1,0] and [2,5,6,9,8,8] are not sharpened.

You can do the following operation as many times as you want: choose any strictly positive element of the array, and decrease it by one. Formally, you can choose any i (1≤i≤n) such that ai>0 and assign ai:=ai−1.
对于给定的数组,你可以选择任意元素进行不限次数的操作:

Tell if it's possible to make the given array sharpened using some number (possibly zero) of these operations.
输出是否能够通过这种操作使得数组变成sharpened数组。

Input
The input consists of multiple test cases. The first line contains a single integer t (1≤t≤15 000)  — the number of test cases. The description of the test cases follows.

The first line of each test case contains a single integer n (1≤n≤3⋅105).

The second line of each test case contains a sequence of n non-negative integers a1,…,an (0≤ai≤109).

It is guaranteed that the sum of n over all test cases does not exceed 3⋅105.

Output
For each test case, output a single line containing "Yes" (without quotes) if it's possible to make the given array sharpened using the described operations, or "No" (without quotes) otherwise.

Example

input
10
1
248618
3
12 10 8
6
100 11 15 9 7 8
4
0 1 1 0
2
0 0
2
0 1
2
1 0
2
1 1
3
0 1 0
3
1 0 1

output
Yes
Yes
Yes
No
No
Yes
Yes
Yes
Yes
No

Note
In the first and the second test case of the first test, the given array is already sharpened.

In the third test case of the first test, we can transform the array into [3,11,15,9,7,4] (decrease the first element 97 times and decrease the last element 4 times). It is sharpened because 3<11<15 and 15>9>7>4.

In the fourth test case of the first test, it's impossible to make the given array sharpened.

解题思路

这道题最重要的是如何构造上升和下降序列,对于一个数组来说,我们首先找到最大的上升序列,然后找到最大的下降序列,看上升和下降序列是否有交集即可。

那么,对于一个数组,如何从第一个元素开始寻找最大的上升序列?

看起来这个问题有点复杂,其实思路很简单,只要最终数列能够像0,1,2,3...这样排列就好。也就是从第一个元素 开始,判定它是否 。第一个元素是否能通过操作达到0,第二个元素是否能达到1,依次类推。

下降序列是一样的道理,从最后一个元素开始,只要能够像...,3,2,1,0这样排列就好,也就是最后一个元素能否达到0,倒数第二个能否到达1,依次向前。

源代码C++

#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define ull unsigned long long
#define rint register int
#define rep(i, l, r) for (rint i = l; i <= r; i++)
#define per(i, l, r) for (rint i = l; i >= r; i--)
#define mset(s, _) memset(s, _, sizeof(s))
#define pb push_back
#define pii pair<int, int>
#define mp(a, b) make_pair(a, b)

inline int read()
{
int x = 0, neg = 1;
char op = getchar();
while (!isdigit(op))
{
if (op == '-')
neg = -1;
op = getchar();
}
while (isdigit(op))
{
x = 10 * x + op - '0';
op = getchar();
}
return neg * x;
}

inline void print(int x)
{
if (x < 0)
{
putchar('-');
x = -x;
}
if (x >= 10)
print(x / 10);
putchar(x % 10 + '0');
}

const int N = 300005;
int a[N], n;
int b[N], c[N];

int main()
{
int T = read();
// 读取用例数
while (T--)
{
// 读取数组数量
n = read();

for (rint i = 1; i <= n; i++)
{
a[i] = read();
//用b和c记录a的相对值
b[i] = a[i] - (i - 1);
c[i] = a[i] - (n - i);
}

int Left = 0, Right = n + 1;

// 双指针
while (Left < n && b[Left + 1] >= 0)
Left++;
while (Right > 0 && c[Right - 1] >= 0)
Right--;
// 是否具有交集
if (Left >= Right)
puts("Yes");
else
puts("No");
}
return 0;
}

题目来源:https://codeforces.com/contest/1291/problem/b


温馨提示




点赞的时候,请宠溺一点