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
    ");
    }
  • 相关阅读:
    Jenkins的插件管理(安装和更新插件)
    [Flutter] MacOS/Windows Flutter 环境走一遍
    [Sw] 使用 Swoole Server task/协程 处理大数据量异步任务时注意
    [Sw] Swoole-4.2.9 可以尝试愉快应用 Swoole 协程
    [PHP] 常备的现代 PHP 项目开发准备
    [SF] Symfony 标准 HttpFoundationRequest 实现分析
    [Linux] umask 从三类人群的权限中拿走权限数字
    [Design] 后端程序的高并发与异步
    [Linux]系统管理: 进程管理(ps/top/pstree/kill/pkill), 工作管理, 系统资源查看, 系统定时任务
    [FE] 有效开展一个前端项目-V2 (vuejs-templates/webpack)
  • 原文地址:https://www.cnblogs.com/zsben991126/p/12155688.html
Copyright © 2011-2022 走看看