首页 > 试题广场 >

交叉线

[编程题]交叉线
  • 热度指数:5212 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
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"。
示例1

输入

2
4
0 10 5 15
4
0 15 5 10

输出

y
n
#include <bits/stdc++.h>
using namespace std;

bool F(int l1, int r1, int l2, int r2){
    return (l2<r1 && l2>l1 && r2>r1) || (r2<r1 && r2>l1 && l2<l1);
}

int main(){
    int T,n,l1,r1,l2,r2;
    cin>>T;
    while(T--){
        cin>>n;
        int a[n];
        for(int i=0;i<n;i++)
            cin>>a[i];
        bool flag = true;
        for(int i=2;i<n && flag;i++){
            l1 = min(a[i], a[i-1]);
            r1 = max(a[i], a[i-1]);
            for(int j=i-2;j>0;j--){
                l2 = min(a[j], a[j-1]);
                r2 = max(a[j], a[j-1]);
                if(F(l1, r1, l2, r2)){
                    flag = false;
                    break;
                }
            }
        }
        cout<<(flag?'n':'y')<<endl;
    }
    return 0;
}

发表于 2019-08-24 02:23:45 回复(1)
""""
找到规律本题不难,对连续的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')

发表于 2019-07-16 16:21:48 回复(0)
#include <stdio.h>
#include <stdlib.h>

int min(a,b){
    return  a < b ? a : b;
}
int max(a,b){
    return a > b ? a : b;
}

int main() {
    int T = 0;
    scanf("%d", &T);
    while(T--){
        int n = 0;
        scanf("%d", &n);

        int circle[n-1][2];
        int vec[n];
        
        for(int i = 0; i < n;i++){
            scanf("%d", &vec[i]);
        }
        
        for(int i = 0; i < n-1;i++){
            circle[i][0] = min(vec[i],vec[i+1]);
            circle[i][1] = max(vec[i],vec[i+1]);
        }
        
        int flag = 0;
        for(int i = 0; i < n - 1; i++){
            for(int j = 0; j < i;j++){

                int l1 = circle[i][0], r1 = circle[i][1];
                int l2 = circle[j][0], r2 = circle[j][1];

                if((l1 < l2) && (r1 < r2) && (r1 > l2)){
                    flag = 1; break;
                }
                if((l1 > l2) && (l1 < r2) && (r1 > r2)){
                    flag = 1; break;
                }
                
            }
            if(flag) break;
        }
        if(flag) {
            printf("y\n");
        }else {
            printf("n\n");
        }

    }
    return 0;
}

发表于 2024-06-13 00:25:54 回复(0)
def xj(interval_a, interval_b):
    start_a, end_a = interval_a
    start_b, end_b = interval_b

    # 区间相交的条件是:
    # 区间A的结束值大于区间B的起始值、A结束值小于B结束值并且区间B的起始值大于区间A的起始值
    return start_a < start_b and start_b < end_a and end_b>end_a
T=int(input())
lm=[]
for _  in range(T):
    n=int(input())
    l=list(map(int,input().split()))
    for i in range(n-1):
        x=sorted(l[i:i+2])
        l[i]=x
    l.remove(l[-1])
    l.sort(key=lambda x:x[0])
    m=False
    for j in range(len(l)):
        for k in range(j+1,len(l)):
            if xj(l[j],l[k]):
                print('y')
                m=True
                break
        if m:
            break
    else:print('n')

发表于 2024-04-11 17:16:20 回复(0)
不知道为什么有部分测试用例会出现 lsit index out of range的情况
import sys
group=int(input())#获取组数
for f in range(group):
    num=int(input())#获取点数
    points=list(map(int,input().split()))#坐标
    flag=False
    for n in range(num//2):#对于每个圆
        cur_round=[points[2*n],points[2*n+1]]
        # print(cur_round)
        others=points[0:2*n]+points[2*n+2:]
        # print(len(others))
        for i in range(0,len(others),2):#对比每个圆是否只有一个点在其他圆内
            # print(i)
            # print(cur_round[0],others[i],others[i+1])
            # print(cur_round[1],others[i],others[i+1])
            if cur_round[0]>others[i] and cur_round[0]<others[i+1]:
                flag=not flag
                
            if cur_round[1]>others[i] and cur_round[1]<others[i+1]:
                flag=not flag
            if flag:
                print("y")
                break
        if flag:
            break
    if flag:
        continue
    print("n")

发表于 2023-09-15 18:20:26 回复(0)
count1=int(input())
list1=[]
list2=[]
for i in range(count1):
    list1.append(int(input()))
    list2.append(list(map(int,input().split())))
def func1(lst):
    lst1=[-1,-1]
    lst2=[]
    result='n'
    for i in range(len(lst)-1):
        lst1[0],lst1[1]=lst[i],lst[i+1]
        lst1.sort()
        lst2.append(tuple(lst1))
    for j in range(1,len(lst2)):
        for k in range(0,j):
            if lst2[j][0]>lst2[k][0] and lst2[j][0]<lst2[k][1]:
                if lst2[j][1]>lst2[k][1]:
                    result='y'
                    return result
            if lst2[j][1]>lst2[k][0] and lst2[j][1]<lst2[k][1]:
                if lst2[j][0]<lst2[k][0]:
                    result='y'
                    return result
    return result
for x in range(len(list2)):
    print(func1(list2[x]))
        
发表于 2022-07-20 22:52:43 回复(0)
使用map<int, vector<int>>储存所有区间的左右边界
对于相同左边界的区间,其右边界存为vector
判断区间相交:设当前区间的左边界为left,最大右边界为maxr,
二分查找前一个区间中第一个大于left的右边界right,若maxr>right,即相交

#include <bits/stdc++.h> // C++万能头文件
using namespace std;
static const auto io_sync_off = [](){ // lambda表达式
    std::ios::sync_with_stdio(false); // 解除与scanf()等函数的同步
    std::cin.tie(nullptr); // 解除cin和cout的绑定
    return nullptr;
}();

int main() {
    int T;
    cin >> T;
    while (T--) {
        int n;
        cin >> n;        
        map<int, vector<int>> mp; // 相同左边界的所有右边界
        int pre, cur;
        cin >> pre;
        for (int i = 1; i < n; ++i) {
            cin >> cur;
            int l = min(pre, cur), r = max(pre, cur);
            mp[l].push_back(r);
            pre = cur;
        }
        if (n <= 2) {
            cout << "n" << endl;
            continue;
        }
        bool cross = false;
        auto iter = mp.begin();
        vector<int> prev = iter->second;
        sort(prev.begin(), prev.end());
        iter++;
        while (iter != mp.end()) {
            vector<int> curv = iter->second;
            sort(curv.begin(), curv.end());
            int left = iter->first;
            int i = upper_bound(prev.begin(), prev.end(), left) - prev.begin();
            if (i < prev.size()) { // prev[i] > left
                int maxr = curv.back();
                if (maxr > prev[i]) {
                    cross = true;
                    break;
                }
            }
            prev = move(curv);
            ++iter;
        }
        if (cross) cout << "y" << endl;
        else cout << "n" << endl;
    }
    return 0;
}


发表于 2022-07-10 01:29:52 回复(0)
python3:
最后一组超时啦
while True:
    try:
        n = int(input())
        for case in range(n):
            m1 = int(input())
            list1 = list(map(int,input().split()))
            one = list()
            for i in range(len(list1)):
                if i <m1-1:
                    one.append((list1[i],list1[i+1]))
            count = 0
            flag = False
            #print(one)
            for i in one:
                k1,k2 = i[0],i[1]
                count+=1
                for j in range(count,len(one)):
                    ppp = one[j]
                    p1,p2 = ppp[0],ppp[1]
                    
                    if (min(k1,k2)<min(p1,p2) and max(k1,k2)>min(p1,p2) and max(k1,k2)<max(p1,p2))&nbs***bsp;(max(k1,k2)>max(p1,p2) and min(k1,k2)<max(p1,p2) and min(k1,k2)>min(p1,p2)):
                        flag =True
                        break
                else:
                    continue
                break
            if flag == True:
                print('y')
            else:
                print("n")
                        
        
    except:
        break

发表于 2022-01-08 18:31:48 回复(0)
import java.util.*;
public class Main{
    private static final int COUNT=6;
    public static void main(String[] args){
        Scanner sc=new Scanner(System.in);
        while(sc.hasNext()){
            int t=sc.nextInt();
            for(int i=0;i<t;i++){
                boolean bool=true;
                int n=sc.nextInt();
                TreeSet<Integer> set=new TreeSet<>();
                int a=sc.nextInt();
                set.add(a);
                for(int j=1;j<n;j++){
                    int b=sc.nextInt();
                    set.add(b);
                    int max=Math.max(a,b);
                    int min=Math.min(a,b);
                    if(bool&&(max!=set.higher(min))&&!(min==set.first()&&max==set.last())){
                        bool=false;
                    }
                    a=b;
                }
                if(bool)
                    System.out.println("n");
                else
                   System.out.println("y"); 
            }
        }
        sc.close();
    }
}

发表于 2021-03-25 14:58:15 回复(0)
//java也需要一席之地
import java.util.*;

public class Main{
    public static void main(String[] args){
        Scanner scan=new Scanner(System.in);
        while(scan.hasNext()){
            int t=scan.nextInt();
            for(int x=0;x<t;x++){
                int n=scan.nextInt();
                int[] arr=new int[n];
                for(int i=0;i<n;i++){
                    arr[i]=scan.nextInt();
                }
                boolean b=find(arr);
                if(b) System.out.println("y");
                else System.out.println("n");
            }
        }
        scan.close();
    }

    public static boolean find(int[] arr){
        if(arr.length<=3) return false;
        for(int i=2;i+1<arr.length;i+=2){
            int l=Math.min(arr[i],arr[i+1]);
            int r=Math.max(arr[i],arr[i+1]);
            for(int j=i-2;j>=0;j-=2){
                int l1=Math.min(arr[j],arr[j+1]);
                int r1=Math.max(arr[j],arr[j+1]);
                if(l1<l&&r1<r&&l<r1){
                    return  true;
                }else if(l1>l&&l1<r&&r1>r){
                    return true;
                }
            }
        }
        return false;
    }
}

发表于 2020-07-21 13:54:29 回复(0)
//没想到暴力也能解答  一直以为有优化的解法
#include<iostream>
(720)#include<vector>
#include<algorithm>

using namespace std;
bool judge(vector<int> &v){
    vector<vector<int>> cir;
    for (int i = 0; i < v.size()-1; i++){
        int L = min(v[i], v[i+1]);
        int R = max(v[i], v[i+1]);
        cir.push_back(vector<int> {L, R});
    }
    for (int i = 1; i < cir.size(); i++){
        for (int j = 0; j < i; j++){
            if (cir[i][0] < cir[j][0] && cir[i][1] < cir[j][1] && cir[i][1] > cir[j][0]){
                return true;
            }
            else if(cir[i][1] > cir[j][1] && cir[i][0] < cir[j][1] && cir[i][0] > cir[j][0]){
                return true;
            }
        }
    }
    return false;
}
int main(void){
    int T;
    cin>>T;
    vector<int> v;
    int n;
    int num;
    for (int i = 0; i < T; i++){
        cin>>n;
        if (n <= 2){
            cout<<"n"<<endl;
            continue;
        }
        v.clear();
        for (int j = 0; j < n; j++){
            cin>>num;
            v.push_back(num);
        }
        if (judge(v))
            cout<<"y"<<endl;
        else
            cout<<"n"<<endl;
    }
    return 0;
}

发表于 2020-05-10 12:05:07 回复(0)
运行时间1806ms,哈哈
加了个2分判断的快一点,不然过90+到不了100
判断的时候固定了右边界升序,固定选一条线段,在其左边找线段,二分的目的是找到左边的右上界满足所有左边的线段右边界!= 固定线段的右边界,因为相等的时候依照题意不算相交。
因为我们已经做升序了,所以左边线段的右边界一定是<=固定线段的,我们需要这个不等条件不满足。
遍历:
左边的左边界 < 右边的左边界 < 左边的右边界 < 右边的右边界的点。 可以结束了
只需要判断 右边的左边界在(左边的左边界,左边的左边界)里面就行了 
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++就过了不需要优化哈哈

发表于 2019-10-08 16:47:06 回复(0)
递归层数太多,通不过,迭代不太好写吧!
#include<vector>
#include<iostream>
using namespace std;
void func1(vector<int> v,int n,int j,int mini,int mid,int maxi);
void func2(vector<int> v,int n,int j,int mini,int mid,int maxi);
void func3(vector<int> v,int n,int j,int mini,int mid,int maxi);
bool flag=true;
void func1(vector<int> v,int n,int j,int mini,int mid,int maxi){
    //下一个可以<min,可以>max,可以大于mid小于max
    for(int i=j;i<n;i++){
        if(v[i]>maxi) func1(v,n,i+1,mini,maxi,v[i]);
        else if(v[i]<mini) func2(v,n,i+1,v[i],mini,maxi);
        else if(v[i]>mid && v[i]<maxi) func3(v,n,i+1,mid,v[i],maxi);
        else{
            flag=false;
            return;
        }
    }
}
void func2(vector<int> v,int n,int j,int mini,int mid,int maxi){
    //下一个可以<min,可以>max,可以大于min小于mid
    for(int i=j;i<n;i++){
        if(v[i]>maxi) func2(v,n,i+1,mini,maxi,v[i]);
        else if(v[i]<mini) func1(v,n,i+1,v[i],mini,maxi);
        else if(v[i]>mini && v[i]<mid) func3(v,n,i+1,mini,v[i],mid);
        else{
            flag=false;
            return;
        }
    }
}

void func3(vector<int> v,int n,int j,int mini,int mid,int maxi){
    //下一个可以大于min小于mid,可以大于mid小于max
    for(int i=j;i<n;i++){
        if(v[i]>mini && v[i]<mid) func3(v,n,i+1,mini,v[i],mid);
        else if(v[i]>mid && v[i]<maxi) func3(v,n,i+1,mid,v[i],maxi);
        else{
            flag=false;
            return;
        }
    }
}

int main(){
    int t,n;
    cin>>t;
    for(int i=0;i<t;i++){
        cin>>n;
        vector<int> v(n);
        for(int j=0;j<n;j++){
            cin>>v[j];
        }
        if(n<=2){
            cout<<"y"<<endl;
            continue;
        }
        flag=true;
        if(v[0]<v[1]) {
            func1(v,n,2,v[0],v[0],v[1]);
        }
        else{
            func2(v,n,2,v[1],v[1],v[0]);
        }
        if(flag) cout<<"y"<<endl;
        else cout<<"n"<<endl;

    }

    return 0;
}


发表于 2019-04-20 11:23:51 回复(1)
我已经尽量简化计算了,但只要有两层循环就超时😓
if __name__=='__main__':
    try:
        T=int(input().strip())
        for i in range(T):
            n=int(input().strip())
            if n<=3:
                print('n')
            else:
                l=list(map(int,input().strip().split()))
                tag = 'n'
                for j in range(n-3):
                    k=j+2
                    while k+1<n:
                        min1=min(l[j],l[j+1])
                        max1=max(l[j],l[j+1])
                        min2 = min(l[k], l[k + 1])
                        max2 = max(l[k], l[k + 1])
                        if (min1>min2 and max1<max2) or (min1<min2 and max1>max2) or(min1>max2) or (min2>max1):
                            k=k+1
                        else:
                            tag='y'
                            break
                    if tag=='y':
                        break
                print(tag)
    except:
        pass
修改后是这样,可以通过,但枚举条件好像有点傻😂
if __name__=='__main__':
    try:
        T = int(input().strip())
        for i in range(T):
            n = int(input().strip())
            if n <= 3:
                print('n')
            else:
                l = list(map(int, input().strip().split()))
                l1 = []
                for j in range(n):
                    l1.append((j, l[j]))
                l1=sorted(l1, key=lambda s: s[1])
                tag = 'n'
                for k in range(n - 1):
                    a = l1.index((l1[k][0], l[l1[k][0]]))
                    b = l1.index((l1[k+1][0], l[l1[k+1][0]]))
                    al = l1.index((l1[k][0] - 1,l[l1[k][0] - 1])) if l1[k][0] > 0 else None
                    ar = l1.index((l1[k][0] + 1,l[l1[k][0] + 1])) if l1[k][0] < n - 1 else None
                    bl = l1.index((l1[k + 1][0] - 1,l[l1[k + 1][0] - 1])) if l1[k + 1][0] > 0 else None
                    br = l1.index((l1[k + 1][0] + 1,l[l1[k + 1][0] + 1])) if l1[k + 1][0] < n - 1 else None
                    if al and bl and ((al < b and b < a) and (bl > a or bl < al)):
                        tag = 'y'
                        break
                    if al and bl and ((al < bl and bl < a) and (b > a or b < al)):
                        tag = 'y'
                        break
                    if al and br and ((al < b and b < a) and (br > a or br < al)):
                        tag = 'y'
                        break
                    if al and br and ((al < br and br < a) and (b > a or b < al)):
                        tag = 'y'
                        break
                    if ar and bl and ((ar < b and b < a) and (bl > a or bl < ar)):
                        tag = 'y'
                        break
                    if ar and bl and ((ar < bl and bl < a) and (b > a or b < ar)):
                        tag = 'y'
                        break
                    if ar and br and ((ar < b and b < a) and (br > a or br < ar)):
                        tag = 'y'
                        break
                    if ar and br and ((ar < br and br < a) and (b > a or b < ar)):
                        tag = 'y'
                        break
                    if al and bl and ((b < al and al < bl) and (a > bl or a < b)):
                        tag = 'y'
                        break
                    if al and bl and ((b < a and a < bl) and (al > bl or al < b)):
                        tag = 'y'
                        break
                    if ar and bl and ((b < ar and ar < bl) and (a > bl or a < b)):
                        tag = 'y'
                        break
                    if ar and bl and ((b < a and a < bl) and (ar > bl or ar < b)):
                        tag = 'y'
                        break
                    if al and br and ((b < al and al < br) and (a > br or a < b)):
                        tag = 'y'
                        break
                    if al and br and ((b < a and a < br) and (al > br or al < b)):
                        tag = 'y'
                        break
                    if ar and br and ((b < ar and ar < br) and (a > br or a < b)):
                        tag = 'y'
                        break
                    if ar and br and ((b < a and a < br) and (ar > br or ar < b)):
                        tag = 'y'
                        break
                print(tag)
    except:
        pass

发表于 2019-04-16 10:07:12 回复(0)