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\n",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]\n",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\n");
    else
        printf("%d\n",ans);
    return 0;
}
posted @ 2019-05-22 08:10  dreagonm  阅读(180)  评论(0编辑  收藏  举报