洛谷$P1712\ [NOI2016]$区间 线段树

正解:线段树

解题报告:

传送门$QwQ$

$umm$很久以前做的了来补个题解$QwQ$

考虑给每个区间按权值($r-l$从大往小排序,依次加入,然后考虑如果有一个位置被覆盖次数等于$m$了就可以把权值最大的那个删去直到被覆盖次数小于$m$,顺便更新答案

然后就做完辣!$QwQ$

放下代码趴,然后因为是去年的代码了所以码风可能有点丑,,,懒得改了$QwQ$

$over$

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int n,m,b[],c[],d[],mx[],add[],l=,r=,ans=0x7fffffff,num;
struct seg
{
int x,y,len;
inline bool operator <(const seg& rhs) const
{
return len>rhs.len;
}
}a[];
inline int read()
{
char ch=getchar();int x=;
while(ch>'' || ch<'')ch=getchar();
while(ch<='' && ch>='')x=(x<<)+(x<<)+(ch^''),ch=getchar();
return x;
}
inline void ins(int l,int r,int x,int y,int k,int v)
{
if (x<=l&&y>=r)
{
add[k]+=v;
mx[k]+=v;
return;
}
int mid=l+r>>;
if (x<=mid) ins(l,mid,x,y,k<<,v);
if (y>mid) ins(mid+,r,x,y,k<<|,v);
mx[k]=max(mx[k<<],mx[k<<|]);
mx[k]+=add[k];
}
int low(int x)
{
int l=,r=num,mid;
while (l<r)
{
mid=(l+r)>>;
if (b[mid]>=x) r=mid;
else l=mid+;
}
return l;
}
int main()
{
n=read(),m=read();
num=;
for (int i=;i<=n;i++)
{
a[i].x=read();
a[i].y=read();
a[i].len=a[i].y-a[i].x;
b[++num]=a[i].x;
b[++num]=a[i].y;
}
sort(a+,a+n+);
sort(b+,b+num+);
for (int i=;i<=n;i++) a[i].x=low(a[i].x),a[i].y=low(a[i].y);
for (int r=;r<=n;r++)
{
ins(,num,a[r].x,a[r].y,,);
while (mx[]>=m)
{
ans=min(ans,a[l].len-a[r].len);
ins(,num,a[l].x,a[l].y,,-);
l++;
}
}
if (ans!=0x7fffffff) printf("%d\n",ans);
else printf("-1");
return ;
}
上一篇:2.Magicodes.NET框架之路——策略管理


下一篇:UOJ222 NOI2016 区间 线段树+FIFO队列