https://vjudge.net/problem/CodeForces-1291B
题目大意:给一个数组,
0
<
=
a
i
<
=
1
0
9
0<=a_i<=10^9
0<=ai<=109,你可以对任意
a
i
>
0
a_i>0
ai>0使得
a
i
=
a
i
−
1
a_i=a_i-1
ai=ai−1。问经过若干次操作后,能否找到一个
k
(
1
<
=
k
<
=
n
)
k(1<=k<=n)
k(1<=k<=n),使得
a
1
<
…
…
<
a
k
a_1<……<a_k
a1<……<ak且
a
k
>
…
…
>
a
n
a_k>……>a_n
ak>……>an。
思路:不妨先假设 k > 1 k>1 k>1,也就是说 a 1 , … … , a k a_1,……,a_k a1,……,ak一定是单调上升的,那么根据贪心策略,该序列一定可以转换成最优序列: 0 , 1 , … … , k − 1 0,1,……,k-1 0,1,……,k−1。也就是说如果 a [ i ] > = i a[i]>=i a[i]>=i,则可以令 a [ i ] = i a[i]=i a[i]=i,如果 a [ i ] < i a[i]<i a[i]<i,说明出现了拐点,也就是说 a i − 1 , a i , … … , a n a_{i-1},a_i,……,a_n ai−1,ai,……,an必须要单调下降,所以有 a i = m i n ( a i , a i − 1 − 1 ) a_i=min(a_i,a_{i-1}-1) ai=min(ai,ai−1−1),如果出现了 a i < 0 a_i<0 ai<0则说明不符题意。那么 k = 1 k=1 k=1的情况怎么处理呢?我们可以用一个数组 b b b, b b b是 a a a的逆序表示,然后再用上述方法对 b b b进行判断,如果可行就是满足题意的。
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn=3e5+5;
int n;
int a[2][maxn];
bool check(int id)
{
int idx=-1;
for(int i=0;i<n;i++)
{
if(a[id][i]>=i)
a[id][i]=i;
else
{
idx=i;
break;
}
}
if(idx==-1)
return 1;
bool flag=1;
for(int i=idx;i<n&&flag;i++)
{
if(a[id][i]>=a[id][i-1])
a[id][i]=a[id][i-1]-1;
if(a[id][i]<0)
flag=0;
}
return flag;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[0][i]);
for(int i=0;i<n;i++)
a[1][i]=a[0][n-i-1];
if(check(0)||check(1))
printf("YES\n");
else
printf("NO\n");
}
return 0;
}