zoukankan      html  css  js  c++  java
  • cf1284D——线段树,排序

    /*
    原问题可以简化成:给定n对区间[sai,eai],[sbi,ebi],
                是否存在i,j,使[sai,eai],[saj,eaj] 与[sbi,ebi],[sbj,ebj]有且仅有一组相交
     
    思路:遍历第i对区间,先找到a部分和[sai,eai]相交的所有段,设这个段的集合为S,
          由于题意,S中所有b部分的段都要和[sbi,ebi]相交,这就要求S中最小的ebj>=sbi,最大的sbj<=ebi
          所以想到一开始就对所有的段,按照eai升序排序,然后二分找到[x,i-1]的段a部分和i的a部分相交,
          再用线段树查询b部分两端的极值,和bi进行比较即可 
    最后swap一下ab再算一次就好 
    */
    #include<bits/stdc++.h>
    #define N 200005
    using namespace std;
    struct Seg{int sa,ea,sb,eb;}p[N];
    int cmp(Seg &a,Seg &b){
        if(a.ea!=b.ea)return a.ea<b.ea;
        else return a.sa<b.sa;
    }
    int n,mx[4*N], mi[4*N];
    void creat(int l, int r, int k)
    {
        if(l == r){
            mx[k]=p[l].sb, mi[k]=p[l].eb;
            return ;
        }
        int mid = (l+r)/2;
        creat(l, mid, 2*k);
        creat(mid+1, r, 2*k+1);
        mx[k] = max(mx[2*k], mx[2*k+1]);
        mi[k] = min(mi[2*k], mi[2*k+1]);
    }
     
    int querymin(int l, int r, int al, int ar, int k)
    {
        if(l == al && r == ar)return mi[k];
        int mid = (l+r)/2;
        if(ar <= mid)return querymin(l, mid, al, ar, 2*k);
        else if(al > mid)return querymin(mid+1, r, al, ar, 2*k+1);
        else return min(querymin(l, mid, al, mid, 2*k),
                        querymin(mid+1, r, mid+1, ar, 2*k+1));
    }
     
    int querymax(int l, int r, int al, int ar, int k)
    {
        if(l == al && r == ar)return mx[k];
        int mid = (l+r)/2;
        if(ar <= mid)return querymax(l, mid, al, ar, 2*k);
        else if(al > mid)return querymax(mid+1, r, al, ar, 2*k+1);
        else return max(querymax(l, mid, al, mid, 2*k),
                        querymax(mid+1, r, mid+1, ar, 2*k+1));
    } 
     
    int ea[N];
    int solve(){
        std::sort(p+1,p+1+n,cmp);
            creat(1,n,1);
        for(int i=1;i<=n;i++)ea[i]=p[i].ea;
        for(int i=1;i<=n;i++){
            if(i==1)continue;
            int left = p[i].sa;
            
            //二分找到
            int ans=lower_bound(ea+1,ea+i,left)-ea;
            if(ans>i-1)continue;
            
            //判断b部分是否合法 
            int maxL=querymax(1,n,ans,i-1,1);
            int minR=querymin(1,n,ans,i-1,1);
            if(minR<p[i].sb || maxL>p[i].eb)
                return 0;
        }
        return 1;
    }
     
    int main(){
    /*    cin>>n;
        for(int i=1;i<=n;i++)
            cin>>p[i].sa>>p[i].ea>>p[i].sb>>p[i].eb;
        int res=solve(); 
        for(int i=1;i<=n;i++)
            swap(p[i].sa,p[i].sb),swap(p[i].ea,p[i].eb);
        res &= solve();
        
        if(res)puts("YES");
        else puts("NO");
    */
        int  i, j, k, sig = 1;
        scanf("%d", &n);
        for(i=1;i<=n;i++)
            scanf("%d %d %d %d", &p[i].sa, &p[i].ea, &p[i].sb, &p[i].eb);
        sig &= solve();
        for(i=1;i<=n;i++)
            swap(p[i].sa, p[i].sb), swap(p[i].ea, p[i].eb);
        sig &= solve();
        if(sig)printf("YES
    ");
        else printf("NO
    ");
    }
  • 相关阅读:
    Go map 切片
    Go map 增删改查和遍历
    Go map 基本使用
    Go 二维数组
    Go 切片
    Go 数组
    Go 错误处理 defer recover panic
    Go time模块
    5分钟入门MP4文件格式
    写盘工具
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12155688.html
Copyright © 2011-2022 走看看