题目链接:点击这里
题目大意:
给出一个长度为
n
n
n 的序列
a
a
a ,有
q
q
q 次询问,每次询问含有一组
l
,
r
l,r
l,r 求
a
l
a_l
al 到
a
r
a_r
ar 中是否能找出三条边使之构成三角形
题目分析:
我们先从暴力出发,我们发现:
对于一次询问的
l
,
r
l,r
l,r 我们将
a
l
a_l
al 到
a
r
a_r
ar 进行从小到大的排序,然后逐个枚举相邻三个的元素,如果满足
a
[
i
]
+
a
[
i
+
1
]
>
a
[
i
+
2
]
a[i]+a[i+1]>a[i+2]
a[i]+a[i+1]>a[i+2] 则可以构成三角形,如果
a
[
i
]
a[i]
a[i] 和
a
[
i
+
1
]
a[i+1]
a[i+1] 都不能和
a
[
i
+
2
]
a[i+2]
a[i+2] 构成三角形那么其他的数更没办法满足两边之和大于
a
[
i
+
2
]
a[i+2]
a[i+2] 。但是其复杂度是
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn) 是难以支持
q
q
q 次查询的
我们继续考虑优化
a
[
i
]
+
a
[
i
+
1
]
>
a
[
i
+
2
]
a[i]+a[i+1]>a[i+2]
a[i]+a[i+1]>a[i+2] ,我们发现当让不等号为等号时有
a
[
i
]
+
a
[
i
+
1
]
=
a
[
i
+
2
]
a[i]+a[i+1]=a[i+2]
a[i]+a[i+1]=a[i+2] 此式子为斐波那契数列的递推式,而我们知道斐波那契数列在第
46
46
46 项的时候就爆
i
n
t
int
int 了,题目给出
a
[
i
]
a[i]
a[i] 的范围是
a
[
i
]
≤
1
e
9
a[i]\le 1e9
a[i]≤1e9 ,因此当
r
−
l
+
1
≥
45
r-l+1\ge 45
r−l+1≥45 即区间长度大于
45
45
45 时我们可以直接判断其可以找到三个元素使之作为三角形的三边,对于
r
−
l
+
1
<
45
r-l+1< 45
r−l+1<45 时用之前那个
n
l
o
g
n
nlogn
nlogn 的方法暴力处理即可,其时间复杂度为
O
(
q
45
l
o
g
45
)
O(q45log45)
O(q45log45)
具体细节见代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
int read()
{
int res = 0,flag = 1;
char ch = getchar();
while(ch<'0' || ch>'9')
{
if(ch == '-') flag = -1;
ch = getchar();
}
while(ch>='0' && ch<='9')
{
res = (res<<3)+(res<<1)+(ch^48);//res*10+ch-'0';
ch = getchar();
}
return res*flag;
}
const int maxn = 1e5+5;
const int mod = 1e9+7;
const double pi = acos(-1);
const double eps = 1e-8;
int n,q,a[maxn],tmp[maxn];
int main()
{
n = read();q = read();
for(int i = 1;i <= n;i++)
a[i] = read();
while(q--)
{
int l = read(),r = read();
int len = r-l+1;
if(len >= 45)
{
puts("clynb");
continue;
}
if(len <= 2)
{
puts("clycdd");
continue;
}
for(int i = 0;i < len;i++)
tmp[i] = a[l+i];
sort(tmp,tmp+len);
bool flag = false;
for(int i = 2;i < len;i++)
{
if(tmp[i-2]+tmp[i-1] > tmp[i])
{
flag = true;
break;
}
}
if(flag) puts("clynb");
else puts("clycdd");
}
return 0;
}