1. 程式人生 > >NOI 2016 區間

NOI 2016 區間

隊列 div 線段樹 mas esp post const 一次 put

我們可以貪心的做。

如果不考慮如何判一個點被覆蓋K次的話。這就是一道經典問題。

我們先把線段排序,那麽我們考慮一個隊列。

我們發現我們先把小的塞進隊尾,等到塞的足夠多(存在一個點被覆蓋了K次)我們就更新答案並把隊尾彈出。

我們可以用線段樹維護點的覆蓋次數K。

第一次寫標記永久化,#define max寫炸調半天,果然老年選手該退役了。

#include<bits/stdc++.h>
#define N 500007
#define SIZ 14000007
#define sight(c) (‘0‘<=c&&c<=‘9‘)
#define INF 1000000007
using
namespace std; struct Node{ int a,b,len; inline bool operator < (const Node A)const{ return len<A.len; } }p[N]; inline void read(int &x){ static char c; for (c=getchar();!sight(c);c=getchar()); for (x=0;sight(c);c=getchar())x=x*10+c-48; } void write(int
x){if (x<10) {putchar(0+x); return;} write(x/10); putchar(0+x%10);} inline void writeln(int x){ if (x<0) putchar(-),x*=-1; write(x); putchar(\n); } inline void writel(int x){ if (x<0) putchar(-),x*=-1; write(x); putchar( ); } int root,ls[SIZ],rs[SIZ],mas[SIZ],lazy[SIZ],tot,n,m,ans=INF,tog;
void add(int &node,int l,int r,int LL,int RR,int dla){ if (!node) node=++tog; if (LL<=l&&r<=RR) { mas[node]+=dla,lazy[node]+=dla;return;} int Mid=l+r>>1; if (LL<=Mid) add(ls[node],l,Mid,LL,RR,dla); if (RR> Mid) add(rs[node],Mid+1,r,LL,RR,dla); mas[node]=max(mas[ls[node]],mas[rs[node]])+lazy[node]; } #undef max int main() { read(n); read(m); for (int i=1;i<=n;i++) read(p[i].a),read(p[i].b),p[i].len=p[i].b-p[i].a; sort(p+1,p+n+1); for (int i=1;i<=n;i++) { add(root,0,INF,p[i].a,p[i].b,1); while (mas[1]>=m) { ans=min(ans,p[i].len-p[++tot].len); //cerr<<"sb"<<endl; add(root,0,INF,p[tot].a,p[tot].b,-1); } } writeln(ans==INF?-1:ans); return 0; }

NOI 2016 區間