LibreOJ 2086 「NOI2016」区间 发表于 2019.11.02 | 分类于 题解 | 4 注意到按长度排序之后,显然是有决策单调性的,故可以双指针。 判定的话随便扯个数据结构维护一下( 感觉在 NOI 里面算签到题? 代码: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960#include <cstdio>#include <algorithm>#define ls (p << 1)#define rs (ls | 1)using namespace std;const int N = 5e5;int n,m;int ind[2 * N + 5],len;int ans = 0x3f3f3f3f;struct note{ int l,r,len; inline bool operator<(const note &o) const { return len < o.len; }} a[N + 5];struct node{ int max,tag;} seg[(N << 3) + 10];void update(int l,int r,int k,int p,int tl,int tr){ if(l <= tl && tr <= r) { seg[p].max += k,seg[p].tag += k; return ; } int mid = tl + tr >> 1; l <= mid && (update(l,r,k,ls,tl,mid),1); r > mid && (update(l,r,k,rs,mid + 1,tr),1); seg[p].max = max(seg[ls].max,seg[rs].max) + seg[p].tag;}int query(int l,int r,int p,int tl,int tr){ if(l <= tl && tr <= r) return seg[p].max; int mid = tl + tr >> 1; int ret = 0; l <= mid && (ret = max(ret,query(l,r,ls,tl,mid))); r > mid && (ret = max(ret,query(l,r,rs,mid + 1,tr))); return ret + seg[p].tag;}int main(){ scanf("%d%d",&n,&m); for(register int i = 1;i <= n;++i) scanf("%d%d",&a[i].l,&a[i].r),a[i].len = a[i].r - a[i].l,ind[++len] = a[i].l,ind[++len] = a[i].r; sort(ind + 1,ind + len + 1),len = unique(ind + 1,ind + len + 1) - ind - 1; for(register int i = 1;i <= n;++i) a[i].l = lower_bound(ind + 1,ind + len + 1,a[i].l) - ind,a[i].r = lower_bound(ind + 1,ind + len + 1,a[i].r) - ind; sort(a + 1,a + n + 1),a[0].len = -0x3f3f3f3f; for(register int i = 1,j = 0;i <= n;++i) { update(a[i].l,a[i].r,1,1,1,len); for(;j < i && seg[1].max >= m;++j,update(a[j].l,a[j].r,-1,1,1,len)); ans = min(ans,a[i].len - a[j].len); } printf("%d\n",ans ^ 0x3f3f3f3f ? ans : -1);} 本文作者: Alpha1022 本文链接: https://www.alpha1022.me/articles/loj-2086.htm 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明出处!