CodeForces - 1284D New Year and Conference(二分,线段树)

题目链接

题目大意

  有n个会议,每个会议分为a,b两个会场,ab会场的开会时间各有一个时间端,问对于任意两个会议,有没有在同一个会场冲突,而在另一个会场没有冲突的情况。

解题思路

  大体思路就是对于每一个会议,先在一个会场中找到与其冲突的所有会议,再在对应的另一个会场中找有没有与之不冲突的。
  具体做法是先以a会场的开始时间排序,然后再以排序后b会场的开始时间的最大值与结束时间的最小值建线段树,遍历每一个会议,二分出与当前会议冲突的会议区间,用线段树在b会场中找这个区间内的开始时间的最大值与结束时间的最小值,如果开始时间的最大值比当前会议的结束时间晚或者结束时间的最小值比当前会议的开始时间早,肯定是存在不冲突的会议的。然后在a和b颠倒再来一遍。

代码

const int maxn = 2e5+10;
const int maxm = 2e3+10;
struct I {
	int x1, y1, x2, y2;
	bool operator < (I a) const {
		return x1==a.x1 ? y1<a.y1 : x1<a.x1;
	}
} a[maxn];
int n;
struct T {
	int s, e;
} tree[maxn<<2];
void build(int rt, int l, int r) {
	if (l==r) {
		tree[rt].s = a[l].x2;
		tree[rt].e = a[l].y2;
		return;
	}
	int mid = (l+r)>>1;
	build(rt<<1, l, mid);
	build(rt<<1|1, mid+1, r);
	tree[rt].s = max(tree[rt<<1].s, tree[rt<<1|1].s);
	tree[rt].e = min(tree[rt<<1].e, tree[rt<<1|1].e);
}
int ask1(int rt, int l, int r, int a, int b) {
	if (l>=a && r<=b) return tree[rt].s;
	int mid = (l+r)>>1;
	int maxx = 0;
	if (a<=mid) maxx = max(maxx, ask1(rt<<1, l, mid, a, b));
	if (b>mid) maxx = max(maxx, ask1(rt<<1|1, mid+1, r, a, b));
	return maxx;
}
int ask2(int rt, int l, int r, int a, int b) {
	if (l>=a && r<=b) return tree[rt].e;
	int mid = (l+r)>>1;
	int minn = INF;
	if (a<=mid) minn = min(minn, ask2(rt<<1, l, mid, a, b));
	if (b>mid) minn = min(minn, ask2(rt<<1|1, mid+1, r, a, b));
	return minn; 
}
int solve(int x) {
	int l = 1, r = n+1;
	while(l<r) {
		int mid = (l+r)>>1;
		if (a[mid].x1>a[x].y1) r = mid;
		else l = mid+1;
	}
	return l-1;
}
int main() {
	cin >> n;
	for (int i = 1; i<=n; ++i) {
		cin >> a[i].x1 >> a[i].y1;
		cin >> a[i].x2 >> a[i].y2;
	}
	sort(a+1, a+n+1); build(1, 1, n);
	a[n+1] = {INF, INF, INF, INF};
	int ok = 1;
	for (int i = 1; i<=n; ++i) {
		int x = solve(i);
		if (x==i) continue;
		int l = ask1(1, 1, n, i, x);
		int r = ask2(1, 1, n, i, x);
		if (r<a[i].x2 || l>a[i].y2) ok = 0;
	}
	for (int i = 1; i<=n; ++i) swap(a[i].x1, a[i].x2), swap(a[i].y1, a[i].y2);
	sort(a+1, a+n+1); build(1, 1, n);
	for (int i = 1; i<=n; ++i) {
		int x = solve(i);
		if (x==i) continue;
		int l = ask1(1, 1, n, i, x);
		int r = ask2(1, 1, n, i, x);
		if (r<a[i].x2 || l>a[i].y2) ok = 0;
	}
	if (ok) cout << "YES" << endl;
	else cout << "NO" << endl;
	return 0;	
}
posted @ 2021-02-17 22:11  shuitiangong  阅读(56)  评论(0编辑  收藏  举报