New Year and Conference(二分+线段树)

Filled with optimism, Hyunuk will host a conference about how great this new year will be!

The conference will have nn lectures. Hyunuk has two candidate venues aa and bb. For each of the nn lectures, the speaker specified two time intervals [sai,eai][sai,eai] (sai≤eaisai≤eai) and [sbi,ebi][sbi,ebi] (sbi≤ebisbi≤ebi). If the conference is situated in venue aa, the lecture will be held from saisai to eaieai, and if the conference is situated in venue bb, the lecture will be held from sbisbi to ebiebi. Hyunuk will choose one of these venues and all lectures will be held at that venue.

Two lectures are said to overlap if they share any point in time in common. Formally, a lecture held in interval [x,y][x,y] overlaps with a lecture held in interval [u,v][u,v] if and only if max(x,u)≤min(y,v)max(x,u)≤min(y,v).

We say that a participant can attend a subset ss of the lectures if the lectures in ss do not pairwise overlap (i.e. no two lectures overlap). Note that the possibility of attending may depend on whether Hyunuk selected venue aa or venue bb to hold the conference.

A subset of lectures ss is said to be venue-sensitive if, for one of the venues, the participant can attend ss, but for the other venue, the participant cannot attend ss.

A venue-sensitive set is problematic for a participant who is interested in attending the lectures in ss because the participant cannot be sure whether the lecture times will overlap. Hyunuk will be happy if and only if there are no venue-sensitive sets. Determine whether Hyunuk will be happy.

Input
The first line contains an integer nn (1≤n≤1000001≤n≤100000), the number of lectures held in the conference.

Each of the next nn lines contains four integers saisai, eaieai, sbisbi, ebiebi (1≤sai,eai,sbi,ebi≤1091≤sai,eai,sbi,ebi≤109, sai≤eai,sbi≤ebisai≤eai,sbi≤ebi).

Output
Print “YES” if Hyunuk will be happy. Print “NO” otherwise.

You can print each letter in any case (upper or lower).

Examples
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
Note
In second example, lecture set {1,3}{1,3} is venue-sensitive. Because participant can’t attend this lectures in venue aa, but can attend in venue bb.

In first and third example, venue-sensitive set does not exist.
题意:一个人要开n场会议,每一场会议都要在a,b两个地方。每一场会议在这两个地方都有开始和终止的时间。对于任意两个会议,如果这a场地时间是重合的,那么它在b场地的时间也要是重合的。如果在a场地不重合,那么在b场地也得是不重合的。反过来,如果在b重合,那么在a也得是重合的。在b不重合,a也不重合。问这n场会议的安排能否做到这一点?
思路:对于这n场会议,我们先按在a场地的会议开始时间排序(由大到小),然后我们可以通过二分去查找有多少场会议在a场地是重合的。对于在b场地的会议,我们找出开始时间的最大值x以及结束时间的最小值y,如果x>t[i].e2||y<t[i].s2的话,就说明有时间段不和当前会议相冲突,这样就不对了。这只是对a场地来说的,对于b场地,我们再交换按照相同的套路来一遍就好了。
代码如下:

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

const int maxx=1e6+100;
struct node{
	int s1,e1;
	int s2,e2;
	bool operator <(const node &a)const{
		if(s1!=a.s1) return s1<a.s1;
		else return e1<a.e1;
	}
}t[maxx];
struct Node{
	int l;
	int r;
	int _max;
	int _min;
}p[maxx<<2];
int num[maxx<<2],b[maxx];
int n;
/*-------线段树--------*/
inline void pushup(int cur)
{
	p[cur]._max=max(p[cur<<1]._max,p[cur<<1|1]._max);
	p[cur]._min=min(p[cur<<1]._min,p[cur<<1|1]._min);
}
inline void build(int l,int r,int cur)
{
	p[cur].l=l;
	p[cur].r=r;
	p[cur]._max=p[cur]._min=0;
	if(l==r)
	{
		p[cur]._max=t[l].s2;
		p[cur]._min=t[l].e2;
		return ;
	}
	int mid=l+r>>1;
	build(l,mid,cur<<1);
	build(mid+1,r,cur<<1|1);
	pushup(cur);
}
inline int query_max(int l,int r,int cur)
{
	int L=p[cur].l;
	int R=p[cur].r;
	if(l<=L&&R<=r) return p[cur]._max;
	int mid=L+R>>1;
	if(r<=mid) return query_max(l,r,cur<<1);
	else if(l>mid) return query_max(l,r,cur<<1|1);
	else return max(query_max(l,mid,cur<<1),query_max(mid+1,r,cur<<1|1));
}
inline int query_min(int l,int r,int cur)
{
	int L=p[cur].l;
	int R=p[cur].r;
	if(l<=L&&R<=r) return p[cur]._min;
	int mid=L+R>>1;
	if(r<=mid) return query_min(l,r,cur<<1);
	else if(l>mid) return query_min(l,r,cur<<1|1);
	else return max(query_min(l,mid,cur<<1),query_min(mid+1,r,cur<<1|1));
}
inline bool fcs()
{
	sort(t+1,t+1+n);
	build(1,n,1);
	for(int i=1;i<=n;i++) b[i]=t[i].s1;
	for(int i=1;i<=n;i++)
	{
		int pos=upper_bound(b+1,b+1+n,t[i].e1)-b;
		if(i+1==pos) continue;
		int x=query_max(i+1,pos-1,1);
		int y=query_min(i+1,pos-1,1);
		if(x>t[i].e2||y<t[i].s2) return 0;
	}
	return 1;
}
int main()
{
	scanf("%d",&n);
	int cnt=0;
	for(int i=1;i<=n;i++) //离散化可有可无
	{
		scanf("%d%d%d%d",&t[i].s1,&t[i].e1,&t[i].s2,&t[i].e2);
		num[++cnt]=t[i].s1;
		num[++cnt]=t[i].e1;
		num[++cnt]=t[i].s2;
		num[++cnt]=t[i].e2;
	}
	sort(num+1,num+1+cnt);
	int cnt1=unique(num+1,num+1+cnt)-num-1;
	for(int i=1;i<=n;i++)
	{
		t[i].s1=lower_bound(num+1,num+1+cnt1,t[i].s1)-num;
		t[i].e1=lower_bound(num+1,num+1+cnt1,t[i].e1)-num;
		t[i].s2=lower_bound(num+1,num+1+cnt1,t[i].s2)-num;
		t[i].e2=lower_bound(num+1,num+1+cnt1,t[i].e2)-num;
	}
	int flag=0;
	if(fcs()) flag++;
	for(int i=1;i<=n;i++)
	{
		swap(t[i].s1,t[i].s2);
		swap(t[i].e1,t[i].e2);
	}
	if(fcs()) flag++;
	if(flag==2) cout<<"YES"<<endl;
	else cout<<"NO"<<endl;
	return 0;
}
/*3
1 3 2 4
3 4 5 5
4 5 6 7*/

好久没写线段树都生疏了。。
努力加油a啊,(o)/~

发布了414 篇原创文章 · 获赞 23 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/starlet_kiss/article/details/104080317