• codeforces 1284D. New Year and Conference(线段树)


    题意:有n场讲座,有两个场地a和b,如果在a场地开讲座则需要占用[sai,eai],在b场地开讲座则需要占用[sbi,ebi]这个时间段,假如开两场讲座,如果在a场地开不冲突,而b场地开冲突,则称其为敏感的,同理a和b反过来也是一样的,如果ab两场地都冲突则也不是敏感的,先求给定的n场讲座,任意的两两开设是否敏感。

    思路:暴力枚举是O(n^2)复杂度,必定超时,这里可以用线段树或ST表做,达到一个nlogn的复杂度。对于任意一个讲座x,找出所有与x讲座在a场地冲突的讲座,再判断其是否在b场地冲突,如果不是则直接输出“NO”

    首先对所有讲座的sa和ea进行升序,例如讲座 i 的时间片是[x,y],在其时间片上与 i 在a场地冲突的讲座用二分的方法可以枚举出来一个离散化后的区间,然后我们用线段树维护b场地的sb最大值和eb最小值,每次查询出这个区间的

    的sb最大值和eb最小值,此时如果说sb最大值 > y 或者 eb最小值 < x,那么这些表演中必定存在b场地与表演i不冲突的情况,此时直接输出“NO”,把所有的讲座都check一遍,交换ab次序再check即可,上述只检验了在a场地冲突一定在b场地冲突的情况,但并未考虑在b场地冲突而在a场地不冲突的情况。

    总体时间复杂度nlogn。

    AC代码:

     1 #include<iostream>
     2 #include<vector>
     3 #include<cstdlib>
     4 #include<cstdio>
     5 #include<algorithm>
     6 #include<cmath>
     7 #include<cstring>
     8 #include<queue>
     9 #include<map>
    10 using namespace std;
    11 typedef long long ll;
    12 const int maxn = 1e5+200;
    13 struct node{
    14     int sa,ea,sb,eb;
    15     node(){};
    16     node(int a,int b,int c,int d){
    17         sa = a,ea = b,sb = c,eb = d;
    18     }
    19     bool operator<(node cur)const{
    20         if(sa == cur.sa ) return ea<cur.ea ;
    21         return sa < cur.sa ;
    22     }
    23 }point[maxn];
    24 int segt_max[4*maxn],segt_min[4*maxn];
    25 void build(int l,int r,int k){//建两个线段树维护区间最大最小值 
    26     if(l == r) {
    27         segt_max[k] = point[l].sb;
    28         segt_min[k] = point[l].eb;
    29         return ; 
    30     }
    31     int mid = (l+r)/2;
    32     build(l,mid,2*k);
    33     build(mid+1,r,2*k+1);
    34     segt_max[k] = max(segt_max[2*k],segt_max[2*k+1]);
    35     segt_min[k] = min(segt_min[2*k],segt_min[2*k+1]);
    36 }
    37 int queryMin(int l,int r,int al,int ar,int k){//查询区间最小值 
    38     if(l >= al && r <= ar) return segt_min[k];
    39     int mid = (l+r)/2;
    40     if(ar<=mid) return queryMin(l,mid,al,ar,2*k);
    41     else if(al>mid){
    42         return queryMin(mid+1,r,al,ar,2*k+1);
    43     }
    44     else {
    45         return min(queryMin(l,mid,al,mid,2*k),queryMin(mid+1,r,mid+1,ar,2*k+1));
    46     }
    47 } 
    48 int queryMax(int l,int r,int al,int ar,int k){//查询区间最大值 
    49     if(l >= al && r <= ar) return segt_max[k];
    50     int mid = (l+r)/2;
    51     if(ar<=mid) return queryMax(l,mid,al,ar,2*k);
    52     else if(al>mid){
    53         return queryMax(mid+1,r,al,ar,2*k+1);
    54     }
    55     else {
    56         return max(queryMax(l,mid,al,mid,2*k),queryMax(mid+1,r,mid+1,ar,2*k+1));
    57     }
    58 } 
    59 bool check(int n){
    60     sort(point+1,point+1+n);
    61     build(1,n,1);
    62     for(int i = 1;i<=n;i++){
    63         int pos = lower_bound(point+1,point+1+n,node(point[i].ea ,1e9+5000,0,0))-point-1;
    64         //查找与第i场演讲冲突的集合 
    65         if(i+1>pos) continue;//无冲突直接跳过 
    66         //check一下另一个场地的所有表演是否都冲突 
    67         if(queryMin(1,n,i+1,pos,1)<point[i].sb || queryMax(1,n,i+1,pos,1)>point[i].eb){
    68             return false;
    69         }
    70     }
    71     return true;
    72 }
    73 int main()
    74 {
    75     int n;
    76     cin>>n;
    77     int f = 0;
    78     for(int i = 1;i<=n;i++){
    79         cin>>point[i].sa>>point[i].ea>>point[i].sb>>point[i].eb;    
    80     }
    81     if(check(n)) f++;
    82     for(int i = 1;i<=n;i++){
    83         swap(point[i].sa,point[i].sb);
    84         swap(point[i].ea,point[i].eb);
    85     }
    86     if(check(n)) f++;
    87     if(f == 2) cout<<"YES";
    88     else cout<<"NO"; 
    89     return 0;
    90 }
  • 相关阅读:
    【动态规划】数字三角形4
    【动态规划】数字三角形3
    【动态规划】数字三角形2
    被破坏的电力系统
    二分法求函数的零点
    膨胀的木棍
    不重复地输出数
    和为给定数
    乘法游戏
    「AHOI2014/JSOI2014」拼图
  • 原文地址:https://www.cnblogs.com/AaronChang/p/12185459.html
Copyright © 2020-2023  润新知