1. 程式人生 > >LOJ#2086. 「NOI2016」區間

LOJ#2086. 「NOI2016」區間

pla hid 一個點 open noi and getchar fine 就是

$n \leq 500000$個區間,從中挑出一些,使得至少有一個點被$m$個選中區間包含,且選中區間長度的極差最小。

區間題死腦筋晚期:把區間按左端點排序,然後右端點用個優先隊列來彈,然後需要維護下標相差$m$的數字差的最值,可以在$n^2$的時間完美拿到簽到題的60分。

求極差嘛,就是關註最大最小,不如把區間按長度升序,這樣枚舉兩個區間時,可以把大小在他們之間的都加進線段樹觀察是否合法。然鵝,可以發現較長區間R往後枚舉越來越長後,最優的較短區間L不會變小,也就是滿足決策單調性,可以雙指針搞定。

技術分享圖片
 1 //#include<iostream>
 2 #include<cstring>
 3
#include<cstdio> 4 //#include<math.h> 5 //#include<set> 6 //#include<queue> 7 //#include<bitset> 8 //#include<vector> 9 #include<algorithm> 10 #include<stdlib.h> 11 using namespace std; 12 13 #define LL long long 14 int qread() 15 { 16 char c; int s=0,f=1
; while ((c=getchar())<0 || c>9) (c==-) && (f=-1); 17 do s=s*10+c-0; while ((c=getchar())>=0 && c<=9); return s*f; 18 } 19 20 //Pay attention to ‘-‘ , LL and double of qread!!!! 21 22 int n,m; 23 #define maxn 500011 24 struct Line{int x,y,v; bool operator < (const
Line &b) const {return v<b.v;} }p[maxn]; 25 26 int lisa[maxn*2],li=0; 27 struct SMT 28 { 29 struct Node{int ls,rs,Max,add;}a[maxn<<2]; int size,n; 30 void up(int x) {a[x].Max=max(a[a[x].ls].Max,a[a[x].rs].Max);} 31 void build(int &x,int L,int R) 32 { 33 x=++size; 34 if (L==R) return; 35 int mid=(L+R)>>1; 36 build(a[x].ls,L,mid); build(a[x].rs,mid+1,R); 37 } 38 void clear(int N) {n=N; size=0; int x; build(x,1,n);} 39 void addsingle(int x,int v) {a[x].add+=v; a[x].Max+=v;} 40 void down(int x) {if (a[x].add) {addsingle(a[x].ls,a[x].add); addsingle(a[x].rs,a[x].add); a[x].add=0;} } 41 int ql,qr,v; 42 void Add(int x,int L,int R) 43 { 44 if (ql<=L && R<=qr) {addsingle(x,v); return;} 45 down(x); 46 int mid=(L+R)>>1; 47 if (ql<=mid) Add(a[x].ls,L,mid); 48 if (qr>mid) Add(a[x].rs,mid+1,R); 49 up(x); 50 } 51 void add(int x,int y,int V) {ql=x; qr=y; v=V; Add(1,1,n);} 52 }t; 53 54 int main() 55 { 56 n=qread(); m=qread(); 57 for (int i=1;i<=n;i++) 58 {p[i].x=qread(); p[i].y=qread()+1; p[i].v=p[i].y-p[i].x-1; lisa[++li]=p[i].x; lisa[++li]=p[i].y;} 59 sort(p+1,p+1+n); sort(lisa+1,lisa+1+li); li=unique(lisa+1,lisa+1+li)-lisa-1; 60 for (int i=1;i<=n;i++) p[i].x=lower_bound(lisa+1,lisa+1+li,p[i].x)-lisa, 61 p[i].y=lower_bound(lisa+1,lisa+1+li,p[i].y)-lisa; 62 63 t.clear(li); 64 65 int ans=0x3f3f3f3f; 66 for (int i=1,j=1;i<=n;i++) 67 { 68 t.add(p[i].x,p[i].y-1,1); 69 for (;j<=n;j++) 70 { 71 t.add(p[j].x,p[j].y-1,-1); 72 if (t.a[1].Max<m) {t.add(p[j].x,p[j].y-1,1); break;} 73 } 74 if (t.a[1].Max>=m) ans=min(ans,p[i].v-p[j].v); 75 } 76 printf("%d\n",ans==0x3f3f3f3f?-1:ans); 77 return 0; 78 }
View Code

LOJ#2086. 「NOI2016」區間