NOI 2016 區間
阿新 • • 發佈:2018-01-25
隊列 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 usingnamespace 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(intx){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 區間