线段树学习笔记 1
\[\huge\color{cornflowerblue}{\texttt{Segment Tree studying notes: NO.1.}}
\]\[\large\color{gold}{\texttt{Only Problems Here.}}
\]
\[\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}{◢_◤} \]
- OI-WIKI上の线段树
\(\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
的区间全部选取也不影响答案,所以可以直接尺取.
#include
//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=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}{◢_◤} \]