CF Hello2020 D. New Year and Conference


D. New Year and Conference

題意

\(2n\)個區間,分別為\([sa_1,ea_1],[sb_1,eb_1],[sa_2,ea_2],[sb_2,eb_2],\cdots,[sa_n,ea_n],[sb_n,eb_n]\),每兩個區間為一對,共\(n\)對區間。一對中的兩個區間綁定在一起,從n對中選出一個子集。存在一種情況是:子集中某個系列(a或b)區間有區間交,而另外一個系列的區間沒有區間交。如果這個情況發生在某個子集中,則輸出NO,否則輸出YES

分析

先考慮a系列區間交的所有可能,枚舉交點,將包含該交點的所有a區間都放到數軸上,同時把對應的b區間也放在數軸上,那么這些b區間中兩兩之間也必須在某點交。

做法是按照a系列區間的左右端點,存放區間編號於vector中,從左到右掃交點,同時將b區間加到線段樹上,並同時判斷當前加的b區間是否與之前的b區間都交,不是的話輸出NO。

const int inf = 0x3f3f3f3f;
const int N = 400010;
int n;
struct SegTree{
    int l,r;
    int mx,lazy;
}t[N*4];
struct node{
    int l,r,id;
}a[N],b[N];
vector<int> l[N],r[N],alls;

void build(int p,int l,int r){
    t[p].l = l;t[p].r = r;
    if(l == r){
        t[p].mx = t[p].lazy = 0;
        return;
    }
    int mid = l + r >> 1;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    t[p].mx = t[p].lazy = 0;
}
void pushdown(int p){
    if(t[p].lazy){
        t[p*2].mx += t[p].lazy;
        t[p*2+1].mx += t[p].lazy;
        t[p*2].lazy += t[p].lazy;
        t[p*2 + 1].lazy += t[p].lazy;
        t[p].lazy = 0;
    }
}
int ask(int p,int l,int r){
    if(t[p].l >= l && t[p].r <= r){
        return t[p].mx;
    }
    pushdown(p);
    int mid = t[p].l + t[p].r >> 1;
    int res = 0;
    if(mid >= l)res = max(res,ask(p*2,l,r));
    if(mid < r)res = max(res,ask(p*2+1,l,r));
    return res;
}
void add(int p,int l,int r,int val){
    if(t[p].l >= l && t[p].r <= r){
        t[p].mx += val;
        t[p].lazy += val;
        return;
    }
    pushdown(p);
    int mid = t[p].l + t[p].r >> 1;
    if(mid >= l)add(p*2,l,r,val);
    if(mid < r)add(p*2+1,l,r,val);
    t[p].mx = max(t[p*2].mx,t[p*2+1].mx);
}
bool check(node *a,node *b){
    int len = alls.size();
    build(1,1,len);
    for(int i=1;i<=len;i++){
        l[i].clear();
        r[i].clear();
    }
    for(int i=1;i<=n;i++){
        l[a[i].l].push_back(i);
        r[a[i].r].push_back(i);
    }
    int sz = 0;
    for(int i=1;i<=len;i++){
        for(int j=0;j<l[i].size();j++){
            int id = l[i][j];
            //把id鋪上
            int L = b[id].l, R = b[id].r;
            //[L,R] 之間最大值必須為sz
            int res = ask(1,L,R);
            if(res != sz) return false;
            add(1,L,R,1);
            sz++;
        }
        for(int j=0;j<r[i].size();j++){
            int id = r[i][j];
            int L = b[id].l, R= b[id].r;
            add(1,L,R,-1);
            sz--;
        }
    }
    return true;
}
int getId(int x){
    return lower_bound(alls.begin(),alls.end(),x) - alls.begin() + 1;
}
int main()
{
    scanf("%d",&n);
    
    for(int i=1;i<=n;i++){
        scanf("%d%d%d%d",&a[i].l,&a[i].r,&b[i].l,&b[i].r);
        alls.push_back(a[i].l);
        alls.push_back(a[i].r);
        alls.push_back(b[i].l);
        alls.push_back(b[i].r);
        a[i].id = i;
        b[i].id = i;
    }
    sort(alls.begin(),alls.end());
    alls.erase(unique(alls.begin(),alls.end()),alls.end());
    for(int i=1;i<=n;i++){
        a[i].l = getId(a[i].l);
        a[i].r = getId(a[i].r);
        b[i].l = getId(b[i].l);
        b[i].r = getId(b[i].r);
    }
    int c1 = check(a,b);
    int c2 = check(b,a);
    if(c1 && c2){
        puts("YES");
    }else puts("NO");
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM