哈爾濱理工大學第八屆程式設計團隊賽K題
阿新 • • 發佈:2018-12-09
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 intmaxn = 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; }