题意:
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.读入数据较大,请使用高效的读入方式。
思路:
利用sort按照l从小到大排序,若l相同则按照r从小到大排序,然后遍历,二分查找即可。
代码:
#include <stdio.h>
#include <algorithm>
using namespace std;
namespace IO {
const int MX = 4e7;
char buf[MX];
int c, sz;
void begin() {
c = 0;
sz = fread(buf, 1, MX, stdin);
}
inline bool read(int &t) {
while (c < sz && buf[c] != '-' && (buf[c] < '0' || buf[c] > '9')) c++;
if (c >= sz) return false;
bool flag = 0; if(buf[c] == '-') {
flag = 1;
c++;
}
for(t = 0; c < sz && '0' <= buf[c] && buf[c] <= '9'; c++)
t = t * 10 + buf[c] - '0';
if(flag) t = -t;
return true;
}
}
struct node {
int l, r;
}stu[100005];
int n;
bool zcy(node A, node B) {
if (A.l == B.l) {
return A.r < B.r;
}
return A.l < B.l;
};
int erfen(int val) {
int star = 0, endd = n - 1;
int ans = -1;
while(star <= endd) {
int mid = (star + endd) / 2;
if (stu[mid].l <= val) {
star = mid + 1;
} else {
ans = mid;
endd = mid - 1;
}
}
return ans;
}
int main () {
IO::begin();
while (IO::read(n)) {
for (int i = 0; i < n; i++) {
IO::read(stu[i].l);
IO::read(stu[i].r);
}
sort(stu, stu + n, zcy);
int flag = 0;
for (int i = 0; i < n - 1; i++) {
int inx = erfen(stu[i].l);
if (inx == -1) {
break;
}
for (int j = inx; j < n && stu[j].l < stu[i].r; j++) {
if(stu[j].r > stu[i].r) {
flag = 1;
break;
}
}
if (flag) {
break;
}
}
if (flag) {
printf("YES\n");
} else {
printf("NO\n");
}
}
return 0;
}
如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢