1. 程式人生 > >哈爾濱理工大學第八屆程式設計團隊賽K題

哈爾濱理工大學第八屆程式設計團隊賽K題

                     K.汪汪汪

Description

給n個區間[l, r],判斷是否存在區間交叉。即是否存在1 <= i < j <= n,使得li < lj < ri < rj。

Input

多組資料

每組資料第一行一個整數n,第二行到第n + 1行每行兩個數分別代表該區間的左右端點。

Output

如果存在交叉,輸出“YES”;否則輸出“NO”

Sample Input

2

1 3

2 4

3

1 7

2 4

5 6

Sample Output

YES

NO

Hint

1 <= n <= 1e5, 1 <= li < ri <= 2e5, 每組資料中所有的l,r互不相同。

所有組資料n的和不超過1e6.

讀入資料較大,請使用高效的讀入方式。

//套路題 之前做過兩道類似的題目 一道叫“小琪畫畫” 一道叫“天神下凡” ,都是排序然後通過找一個圓的第一級祖先,

判斷一些條件,出結果;

而這道題我的做法也是按照左端點從小到達,相等右端點從大到小排序,然後找左端點第一級祖先

像第二個樣例,三個圓的第一級祖先分別為:0(祖先是平面),1(祖先是第一個圓),1

然後遍歷每個圓 如果出現這個圓的右端點大於它第一級祖先的右端點說明 有交叉 跳出迴圈

程式碼如下:

    #include <iostream>
    #include <cstdio>
    #include <cstdio>
    #include <algorithm>

    using namespace std;

    const int
maxn = 100005; const int inf = 0x7fffffff; struct node { int l,r; } a[maxn]; int cmp(node A,node B) { if(A.l==B.l) return A.r>B.r; return A.l<B.l; } int main() { int n; while(scanf("%d",&n)!=EOF) { int flag = 0; for(int i=1; i<=n; i++) { scanf("%d %d",&a[i].l,&a[i].r); } sort(a+1,a+n+1,cmp); int s[maxn]= {0}; int fa[maxn]={0}; int top=0; for(int i=1; i<=n; i++) { while(top&&a[s[top]].r<=a[i].l) { top--; } fa[i]=s[top]; s[++top]=i; } a[0].r = inf; for(int i=2;i<=n;i++) { if(a[i].r>a[fa[i]].r) { flag = 1; break; } } if(flag) { printf("YES\n"); } else { printf("NO\n"); } } return 0; }