【Codeforces 1284D】New Year and Conference

凄惨...

 写个题解反思一下。

题目链接:

https://codeforces.ml/contest/1284/problem/D

题目大意:

有n个活动要安排,第i个活动在a会场举行 会占用[sa,ea]这段时间,在b会场举行会占用[sb,eb]这段时间。定义一些活动是敏感的:有两个活动在一个场地举行冲突而在另一个场地举行不冲突。问是否存在两两活动是敏感的。

题目思路:

这题开始绕进去了...

果然睡一觉是解决问题的最好办法.

首先,对于任何一个区间[sa.sb],可以找出与他有相交的区间范围:所有 sai >= sa && sai <= ea 的都与当前这个区间相交,也就是说左端点在这个区间内,就必相交(这里不用解释

相交就代表着冲突,所以我们需要看一下,这些区间内的在b场地是否冲突,我们的任务是找到一个不冲突的此时就可以返回false了,所以说这是一个存在性命题,存在性的话只需要最大值大于最大值,最小值小于最小值即可,所以我们记一下这些区间b场地右端点的最小值与b场地左端点的最大值,当且仅当 最小值<当前区间b场地左端点 或者 最大值 > 当前区间b场地右端点时,存在不冲突的现象(区间没有相交)

所以此时,就需要再维护一下 这些点的最小值与最大值。

怎么维护呢?

可以用sa建线段树,每次看一下满足条件的 sai >= sa && sai <= ea,区间的最大值与最小值。

上述思路就会很绕,我就绕进去了。

所以这里我们完全可以考虑一下排序(降维),按照sa升序,这样一来,每个区间的冲突的范围就变为一段连续的区间,此时只需要知道这段区间内的最大值与最小值即可。

这样就不用过多的处理线段树的细节

当然这里没用线段树,涉及到静态区间询问,所以直接st表即可。

Note:当然这里只是考虑了在a冲突,在b不冲突的情况 ,还需要反过来进行考虑一下a不冲突,b冲突的情况。

Code:

/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(2)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=1e17;
const int maxn=1e6+6;
const int mod=1e9+7;
const double eps=1e-3;
inline bool read(ll &num)
{char in;bool IsN=false;
    in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
struct node{
    ll s1,e1,s2,e2;
    bool friend operator<(node a,node b){
        if(a.s1==b.s1) return a.e1<b.e1;
        return a.s1<b.s1;
    }
}save[maxn];

ll st_max[maxn][25];
ll st_min[maxn][25];
ll lg[maxn];
void work()
{
    ll cnt=0;
    for(int i=1;i<=n;i++)
        lg[i]=lg[i/2]+1;
    for(int i=1;i<=n;i++){
        st_max[i][0]=save[i].s2;
        st_min[i][0]=save[i].e2;
    }
    for(int j=1;j<=22;j++)
        for(int i=1;i+(1<<j)-1<=n;i++){
            st_max[i][j]=max(st_max[i][j-1],st_max[i+(1<<(j-1))][j-1]);
            st_min[i][j]=min(st_min[i][j-1],st_min[i+(1<<(j-1))][j-1]);
        }
}
ll query_max(ll x,ll y)
{
    ll len=lg[y-x+1]-1;
    return max(st_max[x][len],st_max[y-(1<<len)+1][len]);//为啥+1
}
ll query_min(ll x,ll y)
{
    ll len=lg[y-x+1]-1;
    return min(st_min[x][len],st_min[y-(1<<len)+1][len]);//为啥+1
}
auto biarySearch(int x,int y){///找一下区间冲突
    int ans_s=-1;
    int l = 1,r = n;
    while(l<=r){
        int mid=(l+r)/2;
        if(save[mid].s1>=x){
            r=mid-1;
            ans_s=mid;
        }
        else l=mid+1;
    }
   // printf("%d\n",ans_s);
    if(ans_s==-1) return make_pair(-1,-1);
    int ans_e=-1;
    l = 1 ,r = n;
    while(l<=r){
        int mid=(l+r)/2;
        if(save[mid].s1<=y){
            l=mid+1;
            ans_e=mid;
        }
        else r=mid-1;
    }
   // debug(y);
  //  debug(save[ans_e].s1);
    //printf("%d\n",ans_e);
    if(ans_e==-1) return make_pair(-1,-1);
   return make_pair(ans_s,ans_e);
}
int Solve(){
    sort(save+1,save+1+n);
    work();
    for(int i=1;i<=n;i++){
        auto p = biarySearch(save[i].s1,save[i].e1);
       // debug(p.first);
     //   debug(p.second);
        if(p.first != -1){
            ll tempmin = query_min(p.first,p.second);
            ll tempmax = query_max(p.first,p.second);

            if(tempmin<save[i].s2||tempmax>save[i].e2){
                return 0;
            }
        }
    }
    return 1;
}
int main(){
    read(n);
    for(int i=1;i<=n;i++){
        read(save[i].s1);
        read(save[i].e1);
        read(save[i].s2);
        read(save[i].e2);
    }
    int f1 = Solve();
    for(int i=1;i<=n;i++){
        swap(save[i].s1,save[i].s2);
        swap(save[i].e1,save[i].e2);
    }
    int f2 = Solve();
    if(f1&&f2) puts("YES");
    else puts("NO");
    return 0;
}
/**
4
1 3 3 4
2 3 3 4
3 3 3 4
4 4 3 4
**/

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章