原题链接:1281 山峰和旗子
由题意可得:
k(k-1)+3<=n
由公式能准确得出k的范围。 比较粗的估计就是 k<=floor(sqrt(n))+2
也就是说,k的量级为sqrt(n)量级
首先是输入与预处理部分,复杂度O(n)
然后,对于每一个范围里的k,都一个个试过去,可以二分,所以复杂度为log k次,每次为k
所以该过程总复杂度为klogk ,即时间复杂度是O(sqrt(n)*log(sqrt(n))),也就是O(sqrt(n)*log(n)),这部分复杂度优于O(n)。
程序代码如下:
#include <cstdio>
#include <cmath>
using namespace std;
#define maxsize 51001
int A[maxsize], n, myresult;
void GetInput()
{
scanf("%d", &n);
for (int i=0; i<n; ++i)
{
scanf("%d", &A[i]);
}
}
void PreProcess()
{
int pos = 0; bool flag = false;
for (int i=n-1; i>0; --i)
{
if (A[i] < A[i-1])
{
flag = true;
}
else
if (A[i] > A[i-1])
{
if (flag)
{
flag = false;
pos = i;
}
}
A[i] = pos;
}
A[0] = pos;
}
bool can_insert_flag(int dist)
{
int pos = A[0];
int num =1;
while (pos && num<dist)
{
pos = A[pos + dist];
++num;
}
if (pos)
{
return true;
}
return false;
}
void Process()
{
if (n<=2)
{
myresult = 0;
return;
}
int upper = int ((sqrt(double(((n-3)<<2)+1))+1)/2) + 1;
int lower = 0, mid;
while (lower<upper-1)
{
mid = (lower + upper)>>1;
if (can_insert_flag(mid))
{
lower = mid;
}
else
{
upper = mid;
}
}
myresult = lower;
}
void doOutput()
{
printf("%d", myresult);
//scanf("%d", &myresult);
}
int main()
{
GetInput();
PreProcess();
Process();
doOutput();
return 0;
}