zoukankan      html  css  js  c++  java
  • P1712 [NOI2016]区间

    思路

    对于这道题,要求求出的相当于是一个方案使得某个点的覆盖次数>=m
    然后可以使用类似two-pointer的写法,按长度排序之后,对每个r,求出答案之后取min
    因为删掉r之后,如果存在解,答案不会变的更劣,如果不存在,则需要继续加入,得到的第一个合法解一定是对于当前的r最优的解
    然后如果插入了多于m个区间其实没有关系,因为答案只和最长区间长度-最短区间长度有关系
    要使用离散化,只动态开点会MLE

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    int ans=0x3f3f3f3f,rx,lx,n,m,Nodecnt,root,num[1000100],numcnt;
    struct Node{
        int lson,rson,maxx,add;
    }Seg[500000*30];
    struct interval{
        int l,r;
        bool operator < (const interval &b) const{
            return (r-l)<(b.r-b.l);
        }
    }I[501000];
    void pushup(int o){
        Seg[o].maxx=max(Seg[Seg[o].lson].maxx,Seg[Seg[o].rson].maxx);
    }
    void pushdown(int o){
        if(Seg[o].add){
            if(!Seg[o].lson)
                Seg[o].lson=++Nodecnt;
            if(!Seg[o].rson)
                Seg[o].rson=++Nodecnt;
            Seg[Seg[o].lson].add+=Seg[o].add;
            Seg[Seg[o].rson].add+=Seg[o].add;
            Seg[Seg[o].lson].maxx+=Seg[o].add;
            Seg[Seg[o].rson].maxx+=Seg[o].add;
            Seg[o].add=0;
        }
    }
    void add(int L,int R,int l,int r,int &o,int c){
        if(!o)
            o=++Nodecnt;
        if(L<=num[l]&&num[r]<=R){
            Seg[o].maxx+=c;
            Seg[o].add+=c;
            return;
        }
        pushdown(o);
        int mid=(l+r)>>1;
        if(L<=num[mid])
            add(L,R,l,mid,Seg[o].lson,c);
        if(R>num[mid])
            add(L,R,mid+1,r,Seg[o].rson,c);
        pushup(o);
    }
    int main(){
        scanf("%d %d",&n,&m);
        for(int i=1;i<=n;i++){
            scanf("%d %d",&I[i].l,&I[i].r);
            num[++numcnt]=I[i].l;
            num[++numcnt]=I[i].r;
        }
        sort(I+1,I+n+1);
        sort(num+1,num+numcnt+1);
        numcnt=unique(num+1,num+numcnt+1)-(num+1);
        // for(int i=1;i<=n;i++){
        //     printf("!%d %d
    ",I[i].l,I[i].r);
        // }
        lx=n+1,rx=n;
        while(rx>=m&&lx>=1){
            while(lx>0&&(rx-lx+1<m||Seg[root].maxx<m)){
                lx--;
                if(lx==0)
                    break;
                add(I[lx].l,I[lx].r,1,numcnt,root,1);
            }
            if(lx==0)
                break;
            // printf("[%d,%d]
    ",lx,rx);
            ans=min(ans,(I[rx].r-I[rx].l)-(I[lx].r-I[lx].l));
            add(I[rx].l,I[rx].r,1,numcnt,root,-1);
            rx--;
        }
        if(ans==0x3f3f3f3f)
            printf("-1
    ");
        else
            printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    CF1095F Make It Connected
    【ZJOI2016】旅行者
    [COCI 2009] OTOCI / 极地旅行社
    Sum in the tree
    MST Unification
    【集训队作业2018】Simple Tree
    [COCI2009]Dvapravca
    python 网络编程-02 多进程的交互案例
    python 日志模块logging
    python 网络编程-01基础
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10903690.html
Copyright © 2011-2022 走看看