zoukankan      html  css  js  c++  java
  • poj 3657

    非常考分析能力的一个题目。

           因为这个答案是满足单调性的,可以二分,转化成判定性问题之后。这么考虑,如果把所有的询问按照回答降序排列,然后每处理一个询问的时候,先看它的区间是否被完全覆盖,如果是,则矛盾,否则把它的区间覆盖。

           解释一下,每次覆盖的时候,意思就是这个位置不能放更小的值,如果有一次询问区间没有空白的位置,证明这个值没有办法放进去。所以矛盾。反之,我们每次都任意找一空白处放进一个值,肯定能构造出解。

           但是,这个题目还要求值是唯一的,所以要一次处理所以相同的值,求交集,如果交集为空,矛盾。否则,查看交集,覆盖并集。

           到这里还有问题,这个题目的范围很大,要离散化,离散化还有一个问题,离散化后的相邻的两个值可能离散化前不相邻,那么覆盖了这两个端点后其实没有覆盖这个区间。

    所以离散化的时候要对这样的点中间空出一个值。

    代码如下

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define ls (t<<1)
    #define rs (t<<1|1)
    #define midt (tr[t].l+tr[t].r>>1)
    using namespace std;
    const int maxn=25000+9;
    int n,q;
    int N;
    struct D
    {
        int id,key;
        bool operator <(const struct D & xx) const
        {
            return key<xx.key;
        }
    }a[maxn<<1];
    
    struct Q
    {
        int l,r,min;
        bool operator <(const struct Q &xx) const
        {
            return min>xx.min;
        }
    }qry[maxn],now[maxn];
    
    struct
    {
        int l,r;
        bool data;
    }tr[maxn<<4];
    
    void maketree(int t,int l,int r)
    {
        tr[t].l=l;
        tr[t].r=r;
        tr[t].data=0;
        if(l==r) return;
        int mid=midt;
        maketree(ls,l,mid);
        maketree(rs,mid+1,r);
    }
    
    void pushdown(int t)
    {
        if(tr[t].data==1)
        {
            tr[ls].data=tr[rs].data=1;
        }
    }
    
    bool query(int t,int l,int r)
    {
        if(l==tr[t].l&&r==tr[t].r)
        return tr[t].data;
        pushdown(t);
        int mid=midt;
        if(r<=mid) return query(ls,l,r);
        else if(mid+1<=l) return query(rs,l,r);
        else
        {
            bool fla=1;
            if(query(ls,l,mid)==0) fla=0;
            if(query(rs,mid+1,r)==0) fla=0;
            return fla;
        }
    }
    
    void modify(int t,int l,int r)
    {
        if(l==tr[t].l&&r==tr[t].r)
        {
            tr[t].data=1;
            return ;
        }
        pushdown(t);
        int mid=midt;
        if(r<=mid) modify(ls,l,r);
        else if(mid+1<=l) modify(rs,l,r);
        else
        {
            modify(ls,l,mid);
            modify(rs,mid+1,r);
        }
        if(tr[ls].data&&tr[rs].data) tr[t].data=1;
        else tr[t].data=0;
    }
    
    bool chk(int ret)
    {
    //    cout<<ret<<endl;
        for(int i=1;i<=ret;i++)
        now[i]=qry[i];
        sort(now+1,now+ret+1);
        maketree(1,1,N);
        for(int i=1,j;i<=ret;i=j)
        {
            int l=now[i].l,r=now[i].r;
            j=i+1;
            while(j<=ret&&now[j].min==now[i].min)
            {
                if(l>now[j].r||now[j].l>r) return false;
                l=max(l,now[j].l);
                r=min(r,now[j].r);
                j++;
            }
            if(query(1,l,r)) return false;
            for(int k=i;k<j;k++)
            modify(1,now[k].l,now[k].r);
        }
        return true;
    }
    
    int main()
    {
    //    freopen("in.txt","r",stdin);
        while(scanf("%d %d",&n,&q)!=EOF)
    //     scanf("%d %d",&n,&q);
        {
            N=q<<2;
            for(int i=1;i<=q;i++)
            {
                scanf("%d %d %d",&qry[i].l,&qry[i].r,&qry[i].min);
                if(qry[i].l>qry[i].r)
                swap(qry[i].l,qry[i].r);
                a[i*2].id=i*2;
                a[i*2].key=qry[i].l;
                a[i*2+1].id=i*2+1;
                a[i*2+1].key=qry[i].r;
            }
            sort(a+2,a+q+q+2);
            a[1].key=-1;
            int lon=0;
            for(int i=2;i<=q+q+1;i++)
            {
                if(a[i].key!=a[i-1].key)
                {
                    lon++;
                    if(a[i].key!=a[i-1].key+1)
                    lon++;
                }
                if(a[i].id&1) qry[a[i].id/2].r=lon;
                else qry[a[i].id/2].l=lon;
            }
            int st=1,ed=q,mid;
            while(st<ed)
            {
    //            printf("%d %d
    ",st,ed);
                mid=st+ed>>1;
                if(chk(mid)) st=mid+1;
                else ed=mid;
            }
            if(st==q&&chk(st))
            printf("0
    ");
            else
            printf("%d
    ",st);
        }
        return 0;
    }
    


  • 相关阅读:
    [20211108]索引分裂块清除日志增加(唯一索引)2.txt
    [20220104]in list 几种写法性能测试.txt
    [20211215]提示precompute_subquery补充.txt
    [20211217]滑稽可笑的程序代码2.txt
    SourceTree通过配置SSH来链接GitLab
    Docker在虚拟机中的安装
    .Net 6 Log4Net【.Net Core】
    es(elasticsearch)磁盘清理记录
    JSON 之 Jackson
    git FAQ
  • 原文地址:https://www.cnblogs.com/bbsno1/p/3253786.html
Copyright © 2011-2022 走看看