大M布置给小M一个题目:首先给出n个在横坐标上的点,然后连续的用半圆连接他们:首先连接第一个点与第二点(以第一个点和第二点作为半圆的直径)。然后连接第二个第三个点,直到第n个点。现在需要判定这些半圆是否相交了,在端点处相交不算半圆相交。如下图所示。
输入的第一行包含一个整数T (1 ≤ T ≤ 10)表示有T组样例。
每组样例的第一行是一个整数n (1≤n≤1000)。
接下来的一行输入有n个用空格隔开的不同的整数a1,a2,...,an (-1000000 ≤ ai ≤ 1000000),(ai,0)表示第i个点在横坐标的位置。
对于每个输入文件,输出T行。
每行输出"y"表示这些半圆有相交或者"n"。
2 4 0 10 5 15 4 0 15 5 10
y n
T = int(input())
def low_low_bound(data,en,value):
st = 0
en-=1
while st<=en:
mid = (st+en)//2
if data[mid][1]<value:
st = mid + 1
else:
en = mid - 1
return en
for _ in range(T):
tmp = int(input())
data = list(map(int,input().split()))
re = []
for i in range(len(data)-1):
re.append((min(data[i],data[i+1]),max(data[i],data[i+1])))
re.sort(key = lambda x:(x[1],x[0]))
b = 'n'
for i in range(1,len(re)):
if b=='y':
break
j_max = low_low_bound(re,i,re[i][1])
#j_max = i-1
for j in range(j_max+1):
if re[i][0]<re[j][1] and re[i][0]>re[j][0]:
b = 'y'
break
print(b) 聪明的你一定想到了,第一次过了90+,肯定是卡的时间边界,那只需要把他改成C++就过了不需要优化哈哈""""
找到规律本题不难,对连续的3个值p1,p2,p3
若p3 落在p1、p2中间,则p1、p2区间两侧不能再取值用flag[]=False标记,
否则,p1、p2构成的区间内不能再取值。
by the way:
本题 -1000000 ≤ ai ≤ 1000000,对每一个整数设置并修改flag 时空复杂度较高,
所以通过排序好的b 只对经过的点设置flag,没有经过的点设置flag是没意义的。
"""
if __name__ == "__main__":
T = int(input())
for _ in range(T):
n = int(input())
a = list(map(int, input().strip().split()))
if len(a) <= 3:
print('n')
continue
b = sorted(a)
flag = [True] * len(b) # 所有点都可取
ans = True # 初始设为没有相交点
p1, p2 = a[0], a[1]
for i in range(2, len(a)):
if flag[b.index(a[i])] == False: # 判断此点是否在之前标记为不可取
ans = False # 存在一个相交点,即停止遍历并输出结果
break
if min(p1, p2) < a[i] < max(p1, p2): # 更新区间外的flag为False
for j in range(0, b.index(min(p1, p2))):
flag[j] = False
for j in range(b.index(max(p1, p2)) + 1, len(b)):
flag[j] = False
else: # 更新区间内flag为False
for j in range(b.index(min(p1, p2)) + 1, b.index((max(p1, p2)))):
flag[j] = False
p1, p2 = p2, a[i]
print('n' if ans else 'y')