先把所有区间按长度从小到大排序,我们选择一些连续的区间就可以得到最优解(最优解加上几个多余的区间就是排好序之后连续的区间)
枚举左右端点,用线段树维护区间加和询问$\max$可以做到$O\left(n^2\log_2n\right)$
但实际上我们只需要从小到大枚举右端点,此时左端点的选择是单调不降的,因为如果当前选择的区间已经满足要求,把左端点往左挪不会使答案变小,时间复杂度$O(n\log_2n)$
#include#include using namespace std;const int inf=2147483647;int mx[4000010],d[4000010];void pushup(int x){mx[x]=max(mx[x<<1],mx[x<<1|1]);}void ad(int x,int v){ d[x]+=v; mx[x]+=v;}void pushdown(int x){ if(d[x]){ ad(x<<1,d[x]); ad(x<<1|1,d[x]); d[x]=0; }}void modify(int L,int R,int v,int l,int r,int x){ if(L<=l&&r<=R)return ad(x,v); pushdown(x); int mid=(l+r)>>1; if(L<=mid)modify(L,R,v,l,mid,x<<1); if(mid <<1|1); pushup(x);}struct seg{ int l,r,d;}p[500010];bool operator<(seg a,seg b){return a.d =m){ ans=min(ans,p[i].d-p[l].d); modify(p[l].l,p[l].r,-1,1,N,1); l++; } } if(ans==inf)ans=-1; printf("%d",ans);}