zoukankan      html  css  js  c++  java
  • D. New Year and Conference

    题意:Hyunuk会举行一场会议今年,会议由n门演讲组成,Hyunuk有两个候选场馆a和b,每门演讲在不同的场馆都有不同的时间段,分别是[sa, ea] [sb, eb],对于任意两个演讲,如果存在一对演讲,在a场馆时间段相交,在b场馆时间段不相交,或者在b场馆时间段相交,在a场馆时间段不相交,那么意味着这场会议是场馆敏感的,输出YES,否则输出NO。

    分析:我们枚举每门演讲i,然后二分查找出和它相交的演讲(在场馆A),然后再判断这两门相交的演讲在场馆B,是否也相交,如果在B不相交,说明是场馆敏感的,同时,我们还需要在B场馆再做一遍这个操作,因为,我们在A场馆二分出来的是和演讲i相交的演讲,然后再去B场馆判断这两门演讲相不相交,因此,我们还需要再做一遍操作,在场馆B中二分,在A场馆中寻找两对相不相交。$$即在A场地冲突是否一定在B场地冲突的情况和在B场地冲突是否一定在A场地冲突的情况都要判断一遍$$

    我们使用stl的lower_bound函数去二分演讲i的相交演讲,返回起点大于等于末尾的演讲,假设返回的位置是pos,pos如果是大于等于i + 1,意味着pos和i之间存在着一个或多个相交区间,这些区间都是相交的,然后我们再去查询这些区间的末端最小值和顶端最大值,即ebmin < sbi || sbmax > ebi,即是否至少存在一个在a中和i相交的区间在b中和i不相交,如果存在,就是敏感的,这个,我们可以采用线段树进行优化,返回给定区间的最小值和最大值。

    //代码借鉴一个博主的

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    const int N = 100005;
    
    struct Node
    {
    	int sa;
    	int ea;
    	int sb;
    	int eb;
    	Node(){}
    	Node(int _sa, int _ea, int _sb, int _eb):sa(_sa), ea(_ea), sb(_sb), eb(_eb){}
    	bool operator<(const Node& rhs)const
    	{
    		if (sa != rhs.sa)
    			return sa < rhs.sa;
    		else
    			return ea < rhs.ea;
    	}
    }node[N];
    
    //线段树
    struct tr
    {
    	//该结点代表的区间
    	int l;
    	int r;
    	//该区间涵盖的演讲的最小值
    	int mi;
    	//该区间涵盖的演讲的最大值
    	int mx;
    }tr[N * 4];
    
    void pushup(int u)
    {
    	tr[u].mi = min(tr[u << 1].mi, tr[u << 1 | 1].mi);
    	tr[u].mx = max(tr[u << 1].mx, tr[u << 1 | 1].mx);
    }
    
    void build(int u, int l, int r)
    {
    	//叶节点
    	if (l == r)
    	{
    		tr[u] = { l, r, node[l].eb, node[l].sb };
    		return;
    	}
    	int mid = (l + r) >> 1;
    	build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    	pushup(u);
    }
    
    //l,r是结点的范围
    int querymin(int u, int l, int r, int al, int ar)
    {
    	if (l == al && r == ar)
    	{
    		return tr[u].mi;
    	}
    	int mid = (l + r) >> 1;
    	if (ar <= mid) return querymin(u << 1, l, mid, al, ar);
    	else if (al > mid) return querymin(u << 1 | 1, mid + 1, r, al, ar);
    	else return min(querymin(u << 1, l, mid, al, mid), querymin(u << 1 | 1, mid + 1, r, mid + 1, ar));
    }
    
    int querymax(int u, int l, int r, int al, int ar)
    {
    	if (l == al && r == ar)
    	{
    		return tr[u].mx;
    	}
    	int mid = (l + r) >> 1;
    	if (ar <= mid) return querymax(u << 1, l, mid, al, ar);
    	else if (al > mid) return querymax(u << 1 | 1, mid + 1, r, al, ar);
    	else return max(querymax(u << 1, l, mid, al, mid), querymax(u << 1 | 1, mid + 1, r, mid + 1, ar));
    }
    
    bool solve(int n)
    {
    	sort(node + 1, node + n + 1);
    
    	//建立线段树
    	build(1, 1, n);
    
    	for (int i = 1; i <= n; ++i)
    	{
    		//二分查找与该lecture相交的lecture
    		int pos = lower_bound(node + 1, node + n + 1, Node(node[i].ea, 1e9 + 5, 0, 0)) - (node + 1);
    
    		//不相交就继续下一次循环
    		if (!(i + 1 <= pos))
    			continue;
    
    		if (querymin(1, 1, n, i + 1, pos) < node[i].sb || querymax(1, 1, n, i + 1, pos) > node[i].eb)
    			return false;
    	}
    
    	return true;
    }
    
    int main()
    {
    	//n个lecture
    	int n;
    
    	scanf("%d", &n);
    
    	for (int i = 1; i <= n; ++i)
    	{
    		scanf("%d%d%d%d", &node[i].sa, &node[i].ea, &node[i].sb, &node[i].eb);
    	}
    	
    	
    	int flag = 1;
    	flag = flag & solve(n);
    
    	for (int i = 1; i <= n; ++i)
    	{
    		swap(node[i].sa, node[i].sb);
    		swap(node[i].ea, node[i].eb);
    	}
    
    	flag = flag & solve(n);
    
    	if (flag)
    		puts("YES");
    	else
    		puts("NO");
    	
    
    
    	return 0;
    }
    
  • 相关阅读:
    系统安全
    导出csv文件示例
    MsChart在MVC下的问题
    记录一些测试的结果
    使用CTE减少统计子查询
    otl获得sql出错位置(oracle)
    在sql语句中使用plsql变量
    Java经典编程题50道之二十四
    Java经典编程题50道之二十三
    Java经典编程题50道之二十二
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/12218557.html
Copyright © 2011-2022 走看看