[Noi2016] Interval BZOJ4653 Luogu P1712 Loj#2086

Forehead...

First of all, seeing this question, the first thought is the binary answer + line segment tree...

Excited to think that I must be able to AC, then I found out that n is 500000...

nlog^2=80%, the test can pass...

Since the answer is to find the maximum length that satisfies the meaning of the question - the minimum length is the smallest, then we can consider sorting the interval by length

After that, because we need the largest and smallest, we must choose to take a continuous segment in the sorted interval to be the optimal situation (at least not worse than others)

So, consider a double pointer swipe to do it...

Is it very watery?

Since I was too lazy to write discretization, I wrote the dynamic open-point line segment tree at the beginning, what the hell am I? mle? ! 256mb can not open!

loj+ 95% on Luogu, with code attached...

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <queue>
using namespace std;
#define N 500005
#define lson l,m,tr[rt].ls
#define rson m+1,r,tr[rt].rs
#define PushUp(rt) tr[rt].maxx=max(tr[tr[rt].ls].maxx,tr[tr[rt].rs].maxx)
struct no
{
	int ls,rs,maxx,add;
}tr[N*40];
int n,m,ans,cnt;
struct node
{
	int l, r, len;
}a[N];
bool cmp(const node &a,const node &b)
{
	return a.len <b.len;
}
void PushDown(int rt)
{
	if(tr[rt].add)
	{
		if(!tr[rt].ls)tr[rt].ls=++cnt;
		if(!tr[rt].rs)tr[rt].rs=++cnt;
		tr[tr[rt].ls].maxx+=tr[rt].add;
		tr[tr[rt].rs].maxx+=tr[rt].add;
		tr[tr[rt].ls].add+=tr[rt].add;
		tr[tr[rt].rs].add+=tr[rt].add;
		tr[rt].add=0;
	}
}
void Update(int L,int R,bool c,int l,int r,int &rt)
{
	if(!rt)rt=++cnt;
	if(L<=l&&r<=R)
	{
		tr[rt].maxx+=c?1:-1;
		tr[rt].add+=c?1:-1;
		return ;
	}
	PushDown(rt);
	int m=(l+r)>>1;
	if(m>=L)Update(L,R,c,lson);
	if(m<R)Update(L,R,c,rson);
	PushUp(rt);
}
intmain()
{
	ans=1<<30;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&a[i].l,&a[i].r);
		a [i] .len = a [i] .ra [i] .l;
	}
	sort(a+1,a+n+1,cmp);
	int l=1,r=0,rot=0;
	while(r<n)
	{
		while(tr[rot].maxx<m&&r<n){r++;Update(a[r].l,a[r].r,1,0,1<<30,rot);}
		if(tr[rot].maxx<m)break;
		while(tr[rot].maxx>=m&&l<n){Update(a[l].l,a[l].r,0,0,1<<30,rot);l++;}
		ans = min (a [r] .len-a [l-1] .len, ans);
	}
	printf("%d\n",ans==1<<30?-1:ans);
	return 0;
}

  This obviously can't be AC, then we can consider using discretization...

After discretization, the space complexity of the line segment tree changes from (nlog(1<<30)) to (nlog(n*2)), and the space decreases...

Attaching the AC code...

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <queue>
using namespace std;
#define N 500005
#define lson l,m,tr[rt].ls
#define rson m+1,r,tr[rt].rs
#define PushUp(rt) tr[rt].maxx=max(tr[tr[rt].ls].maxx,tr[tr[rt].rs].maxx)
struct no
{
	int ls,rs,maxx,add;
}tr[N*10];
int p[N<<1];
int n,m,ans,cnt;
struct node
{
	int l, r, len;
}a[N];
bool cmp(const node &a,const node &b)
{
	return a.len <b.len;
}
void PushDown(int rt)
{
	if(tr[rt].add)
	{
		if(!tr[rt].ls)tr[rt].ls=++cnt;
		if(!tr[rt].rs)tr[rt].rs=++cnt;
		tr[tr[rt].ls].maxx+=tr[rt].add;
		tr[tr[rt].rs].maxx+=tr[rt].add;
		tr[tr[rt].ls].add+=tr[rt].add;
		tr[tr[rt].rs].add+=tr[rt].add;
		tr[rt].add=0;
	}
}
void Update(int L,int R,bool c,int l,int r,int &rt)
{
	if(!rt)rt=++cnt;
	if(L<=l&&r<=R)
	{
		tr[rt].maxx+=c?1:-1;
		tr[rt].add+=c?1:-1;
		return ;
	}
	PushDown(rt);
	int m=(l+r)>>1;
	if(m>=L)Update(L,R,c,lson);
	if(m<R)Update(L,R,c,rson);
	PushUp(rt);
}
intmain()
{
	ans=1<<30;
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&a[i].l,&a[i].r);
		a [i] .len = a [i] .ra [i] .l;
		p[(i<<1)-1]=a[i].l;
		p[i<<1]=a[i].r;
	}
	sort(p+1,p+n*2+1);
	for(int i=1;i<=n;i++)
	{
		int x=lower_bound(p+1,p+n*2+1,a[i].l)-p;
		a[i].l=x;
		x=lower_bound(p+1,p+n*2+1,a[i].r)-p;
		a[i].r=x;
	}
	sort(a+1,a+n+1,cmp);
	int l=1,r=0,rot=0;
	while(r<n)
	{
		while(tr[rot].maxx<m&&r<n){r++;Update(a[r].l,a[r].r,1,1,n*2,rot);}
		if(tr[rot].maxx<m)break;
		while(tr[rot].maxx>=m&&l<n){Update(a[l].l,a[l].r,0,1,n*2,rot);l++;}
		ans = min (a [r] .len-a [l-1] .len, ans);
	}
	printf("%d\n",ans==1<<30?-1:ans);
	return 0;
}

  Discretization or something, just use lower_bound, I'm too lazy to write binary search... Anyway, I won't tle...

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325245749&siteId=291194637