题目链接
题解
这题不难发现可以先确认K,难点在于check取K是否可行。
可以用双端队列实现,确认出k之后,让双端队列中始终保持k个数,从一端pop的同时,另一端push。比较灵活,细节看注释。
代码
/*
* @Author: hesorchen
* @Date: 2020-11-26 09:12:46
* @LastEditTime: 2021-02-03 22:12:26
* @Description: 栽种绝处的花
*/
#include <bits/stdc++.h>
using namespace std;
int a[100010];
deque<int> q;
int main()
{
q.clear();
int n;
cin >> n;
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
int flag = 1, lenth;
for (int i = 1; flag && i <= n; i++) //先确定k的值
{
if (a[i] != i)
{
for (int j = i + 1; flag && j <= n; j++)
{
if (i == a[j])
{
lenth = j - i + 1;
flag = 0;
}
}
}
}
if (flag) //如果本来就有序,直接输出yes
return puts("yes\n1"), 0;
int pos = 1, beg = 1;
while (q.size() < lenth) //先压入lenth个
q.push_back(a[pos++]);
while (pos <= n)
{
int ff = 0;
if (q.front() == beg) //如果前端满足,从前端开始弹出
{
while (pos <= n && q.front() == beg)
{
ff = 1;
beg++;
q.pop_front();
q.push_back(a[pos++]);
}
}
else //如果后端满足,从前端开始弹出
{
while (pos <= n && q.back() == beg)
{
ff = 1;
beg++;
q.pop_back();
q.push_front(a[pos++]);
}
}
if (!ff) //如果两端都不满足,输出no
return puts("no"), 0;
}
//判断队列中最后的lenth个数是不是有序
int now = n - lenth + 1; //剩下的数中,最小的应该是now
if (q.front() == now) //只能选择一端开始弹出
{
while (q.size() && q.front() == now)
{
now++;
q.pop_front();
}
}
else
{
while (q.size() && q.back() == now)
{
now++;
q.pop_back();
}
}
if (q.size() == 0) //如果最后的length数仍然有序,那么输出yes
{
puts("yes");
cout << lenth << endl;
}
else
puts("no");
return 0;
}