做题记录整理数据结构/线段树 P1712 [NOI2016] 区间(2022/10/19)

P1712 [NOI2016] 区间

由于现在做题比较杂,所以就不标号码了

感觉应该算是思维题?
刚开始没想到完全用线段树后来看了题解
如果想到线段树的话这题剩下的东西就可以很自然的想到了
贪心的把区间按区间长度排序
然后用尺取法
看看数据范围会发现需要离散化
好像也不是很好想
至少不算难打

#include<bits/stdc++.h>
#define for1(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
struct node{
    int l;
    int r;
    int mx;
    int lan;
}s[2000005*4];
struct node2{
	int l;
	int r;
	int val;
}a[5000005];
int n,m;
int ll[5000005],rr[500005];
#define ls q*2
#define rs q*2+1

bool cmp(node2 x,node2 y)
{
	return x.val<y.val;
}
void build(int q,int l,int r)
{
	s[q].l=l;
	s[q].r=r;
	if(l==r)
	{
		s[q].mx=0;
		return ;
	}
	int mid=(l+r)>>1;
	build(ls,l,mid);
	build(rs,mid+1,r);
	return ;
}

void chuan(int q)
{
	if(s[q].lan)
	{
		s[ls].lan+=s[q].lan;
		s[ls].mx+=s[q].lan;
		s[rs].lan+=s[q].lan;
		s[rs].mx+=s[q].lan;
		s[q].lan=0;
	}
	return ;
}

void xg(int q,int l,int r,int k)
{
	if(s[q].l>=l&&s[q].r<=r)
	{
		s[q].mx+=k;
		s[q].lan+=k;
		return ;
	}
	chuan(q);
	int mid=(s[q].l+s[q].r)>>1;
	if(l<=mid) xg(ls,l,r,k);
	if(r>mid) xg(rs,l,r,k);
	s[q].mx=max(s[ls].mx,s[rs].mx);
}
int main()
{
	scanf("%d%d",&n,&m);
	
	for1(i,1,n)
	{
		scanf("%d%d",&a[i].l,&a[i].r);
		a[i].val=a[i].r-a[i].l;
		ll[i]=a[i].l;
		ll[i+n]=a[i].r;
	}
	
	sort(ll+1,ll+2*n+1);
	int ji=unique(ll+1,ll+2*n+1)-ll-1;
	for1(i,1,n)
	a[i].l=(lower_bound(ll+1,ll+ji+1,a[i].l)-ll);
	for1(i,1,n)
	a[i].r=(lower_bound(ll+1,ll+ji+1,a[i].r)-ll);

	
	build(1,1,ji);
	sort(a+1,a+n+1,cmp);
	int jl=1;
	int jr=0;
	int ans=1e9;
    while(jl<=n)
    {

        while(jr<n&&s[1].mx<m)
        {
        	    
		    jr++;
			xg(1,a[jr].l,a[jr].r,1);
		}
        if(jr==n &&s[1].mx<m) break;
        ans=min(ans,a[jr].val-a[jl].val);  
		    	xg(1,a[jl].l,a[jl].r,-1);
		jl++;     
    }
    printf("%d\n",(ans==1e9)?-1:ans);
	return 0;
 } 
posted @ 2022-10-19 15:00  yyx525jia  阅读(19)  评论(0)    收藏  举报