input
2
1 2 3 6
3 4 7 8
output
YES
input
3
1 3 2 4
4 5 6 7
3 4 5 5
output
NO
input
6
1 5 2 9
2 4 5 8
3 6 7 11
7 10 12 16
8 11 13 17
9 12 14 18
output
YES
题意
一共有A,B两个会议场,每个会议场会有n场会议,每次给出在A和B会议场进行的第i场会议的时间段
现要求从中任选出k(k>=2)场会议,这k场会议中在A会议场中的状态(向交与否)与在B会议场中的
状态必须相同
思路
第三组样例:
在会议场A中对于一个会议i我们可以二分查找出与它冲突的所有会议,令该会议时间段的集合为S,在B中判断S时间
段的有没有与i区间不相交,若有则不满足题意,之后再反向操作一遍即可
其中判断一个集合中的时间段是否与i区间相交可以用线段树维护区间最值
代码
#pragma GCC optimize(2)
#include<iostream>
#include<unordered_map>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<cmath>
#include<map>
#include<set>
#define Buff ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define rush() int Case = 0; int T; cin >> T; while(T--)
#define rep(i, a, b) for(int i = a; i <= b; i ++)
#define per(i, a, b) for(int i = a; i >= b; i --)
#define reps(i, a, b) for(int i = a; b; i ++)
#define clc(a, b) memset(a, b, sizeof(a))
#define Buff ios::sync_with_stdio(false)
#define readl(a) scanf("%lld", &a)
#define readd(a) scanf("%lf", &a)
#define readc(a) scanf("%c", &a)
#define reads(a) scanf("%s", a)
#define read(a) scanf("%d", &a)
#define lowbit(n) (n&(-n))
#define pb push_back
#define sqr(x) x*x
#define lson rt<<1
#define rson rt<<1|1
#define ls lson, l, mid
#define rs rson, mid+1, r
#define y second
#define x first
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int>PII;
const int mod = 1e9+7;
const double eps = 1e-6;
const int N = 1e5+7;
int Max[N<<2], Min[N<<2];
int n;
struct node
{
int sa, ea, sb, eb;
bool operator < (node t)const{
if(sa == t.sa) return ea < t.ea;
return sa < t.sa;
}
}p[N];
void build(int rt, int l, int r)
{
if(l == r)
{
Max[rt] = p[l].sb;
Min[rt] = p[l].eb;
return ;
}
int mid = l + r >> 1;
build(ls); build(rs);
Max[rt] = max(Max[lson], Max[rson]);
Min[rt] = min(Min[lson], Min[rson]);
}
int QueryMax(int rt, int l, int r, int L, int R)
{
if(l >= L && r <= R) return Max[rt];
int mid = l + r >> 1;
if(R <= mid) return QueryMax(ls, L, R);
else if(L > mid) return QueryMax(rs, L, R);
else return max(QueryMax(ls, L, mid), QueryMax(rs, mid+1, R));
}
int QueryMin(int rt, int l, int r, int L, int R)
{
if(l >= L && r <= R) return Min[rt];
int mid = l + r >> 1;
if(R <= mid) return QueryMin(ls, L, R);
else if(L > mid) return QueryMin(rs, L, R);
else return max(QueryMin(ls, L, mid), QueryMin(rs, mid+1, R));
}
bool judge()
{
sort(p+1, p+n+1);
build(1, 1, n);
rep(i, 1, n)
{
node t = {p[i].ea, mod, 0, 0};
int pos = lower_bound(p+1, p+n+1, t) - p - 1;
if(pos <= i) continue;
int minv = QueryMin(1, 1, n, i+1, pos);
int maxv = QueryMax(1, 1, n, i+1, pos);
if(maxv > p[i].eb || minv < p[i].sb) return false;
}
return true;
}
int main()
{
cin >> n;
rep(i, 1, n)
{
int a, b, c, d;
cin >> a >> b >> c >> d;
p[i] = {a, b, c, d};
}
int res = 0;
if(judge()) res ++;
rep(i, 1, n)
{
swap(p[i].sa, p[i].sb);
swap(p[i].ea, p[i].eb);
}
if(judge()) res ++;
// cout << res <<endl;
puts(res == 2 ? "YES" : "NO");
return 0;
}