线段树学习笔记 1
\[\huge\color{cornflowerblue}{\texttt{Segment Tree studying notes: NO.1.}}
\]
\[\large\color{gold}{\texttt{Only Problems Here.}}
\]
\(\tt{P1712}\) 区间
\[\huge\color{silver}{\texttt{1.锂性分析}}
\]
- 做不出来,爬了爬了
看到题: 哟,标签全都认识,跟网络流的某些水题估计一个水平
1h later: 好我觉得这是正解
然后用1h打了一个既不离散化也不正解的线段树(((
考虑把所有区间按长度排序之后离散化,这样方便尺取统计答案.
尺取代码:
int l=1,r=1;
while(r<=n)
{
	modify(1,nd[r].left,nd[r].right,1);
	while(tr[1].v>=m)
	{
		ans=min(ans,nd[r].len-nd[l].len);
		modify(1,nd[l].left,nd[l].right,-1);
		l++;
	}
	r++;
}
- \(\tt{Cytti\;\;\;\;\boxed{AKer}:为什么不用考虑尺取的时候不连续地取区间更优?}\)
因为区间序列排序后有单调性,答案统计的是有效的区间,即使在答案所选最少区间之外将所有长度介于maxn和minn的区间全部选取也不影响答案,所以可以直接尺取.
\[\huge\color{silver}{\texttt{2.感性开打}}
\]
#include <bits/stdc++.h>
//WA very fucking bad()
#define ri register int
#define MAXN 500005
#define int long long
using namespace std;
const int inf=0x3f3f3f3f;
int n,m;
int ans=inf;
int cnt;
int nd2[MAXN<<1];
struct node{
	int left,right,len;
}nd[MAXN];
inline bool cmp(node a,node b)
{
	return a.len<b.len;
}
inline int r()
{
	int fed=0;
	char in=getchar();
	bool flag=1;
	while(!isdigit(in))
	flag&=(in!='-'),in=getchar();
	while(isdigit(in))
	fed=fed*10+in-'0',in=getchar();
	return (2*flag-1)*fed;
}
struct seg_tree{
	int l,r;
	int tag;
	int v;
}tr[MAXN<<3];
inline void push_up(int u)
{
//	if(tr[u<<1].pos+tr[u<<1].len>=tr[u<<1|1].pos)
//	{
//		tr[u].minn=min(tr[u<<1].minn,tr[u<<1|1].minn);
//		tr[u].maxn=max(tr[u<<1].maxn,tr[u<<1|1].maxn);
//		tr[u].pos=tr[u<<1|1].pos;
//		tr[u].len=tr[u<<1].pos+tr[u<<1].len-tr[u<<1|1].pos;
//		tr[u].tot=tr[u<<1].tot+tr[u<<1|1].tot;
//		//printf("NODE:%d>>> minn=%d maxn=%d pos=%d len=%d tot=%d\n",u,tr[u].minn,tr[u].maxn,tr[u].pos,tr[u].len,tr[u].tot);
//	}
	//以上为女子亻弋石马
	tr[u].v=max(tr[u<<1].v,tr[u<<1|1].v);
}
inline void push_down(int u)
{
	tr[u<<1].tag+=tr[u].tag;
	tr[u<<1|1].tag+=tr[u].tag;
	tr[u<<1].v+=tr[u].tag;
	tr[u<<1|1].v+=tr[u].tag;
	tr[u].tag=0;
}
inline void build(int u,int l,int r)
{
	tr[u].l=l,tr[u].r=r;
	if(l==r)
		return;
	int mid=l+r>>1;
	build(u<<1,l,mid);
	build(u<<1|1,mid+1,r);
}
inline void modify(int u,int l,int r,int d)
{
	if(tr[u].l>=l&&tr[u].r<=r)
	{
		tr[u].tag+=d;
		tr[u].v+=d;
		return;
	}
	if(tr[u].tag)
	push_down(u);
	int mid=tr[u].l+tr[u].r>>1;
	if(l<=mid)
	modify(u<<1,l,r,d);
	if(r>mid)
	modify(u<<1|1,l,r,d);
	push_up(u);
}
signed main()
{
	n=r(),m=r();
	for(ri i=1;i<=n;i++)
	{
		nd[i].left=r();
		nd[i].right=r();
		nd[i].len=nd[i].right-nd[i].left;
		nd2[++cnt]=nd[i].left;
		nd2[++cnt]=nd[i].right;
	}
	sort(nd+1,nd+n+1,cmp);
	sort(nd2+1,nd2+cnt+1);
	int len=unique(nd2+1,nd2+cnt+1)-nd2-1;
	for(ri i=1;i<=n;i++)
	{
		nd[i].left=lower_bound(nd2+1,nd2+len+1,nd[i].left)-nd2;	
		nd[i].right=lower_bound(nd2+1,nd2+len+1,nd[i].right)-nd2;	
	}
	build(1,1,len);
	int l=1,r=1;
	while(r<=n)
	{
		modify(1,nd[r].left,nd[r].right,1);
		while(tr[1].v>=m)
		{
			ans=min(ans,nd[r].len-nd[l].len);
			modify(1,nd[l].left,nd[l].right,-1);
			l++;
		}
		r++;
	}
	if(ans!=inf)
	printf("%lld",ans);
	else
	puts("-1");
	return 0;
}
\[\color{skyblue}{\texttt{And We,}}
\]
\[\color{skyblue}{\texttt{We Burn Faster Than Lights,}}
\]
\[\color{skyblue}{\texttt{Shine Across In The Night Sky,}}
\]
\[\color{skyblue}{\texttt{We Burn Faster Than Lights.}}
\]
\[\color{gold}{◢_◤}
\]

 膜拜 Segment Tree! %%% (?)
        膜拜 Segment Tree! %%% (?)
     
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号