题目大意:
有n个区间,当有m个区间有公共部分时,求m个区间长度的最大值与最小值之差的最小值。
思路:
按区间的长度从小到大排序,可知连续的几个区间最优,则用两个指针指其头尾,线性扫描,再用线段树区间覆盖。
代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #define N 1000009 5 #define INF 2147483647 6 using namespace std; 7 8 int n,m,i,j,cnt,ans=INF,sum[N<<2],lazy[N<<2],b[N<<1]; 9 struct node{ int l,r,len; } a[N]; 10 11 bool cmp(const node &x,const node &y) 12 { 13 return x.len<y.len; 14 } 15 16 int find(int l,int r,int x) 17 { 18 if (l==r) return l; 19 int mid=l+r>>1; 20 if (x<=b[mid]) find(l,mid,x); 21 else find(mid+1,r,x); 22 } 23 24 void up_date(int k,int x) 25 { 26 sum[k]+=x,lazy[k]+=x; 27 } 28 29 void change(int cur,int L,int R,int l,int r,int val) 30 { 31 if (L==l && R==r) { up_date(cur,val); return; } 32 int mid=L+R>>1; 33 if (lazy[cur]) 34 { 35 up_date(cur<<1,lazy[cur]); 36 up_date(cur<<1|1,lazy[cur]); 37 lazy[cur]=0; 38 } 39 if (r<=mid) change(cur<<1,L,mid,l,r,val); 40 else if (l>mid) change(cur<<1|1,mid+1,R,l,r,val); 41 else change(cur<<1,L,mid,l,mid,val),change(cur<<1|1,mid+1,R,mid+1,r,val); 42 sum[cur]=max(sum[cur<<1],sum[cur<<1|1]); 43 } 44 45 void solve() 46 { 47 for (i=1;i<=n;i++) 48 { 49 while (sum[1]<m) 50 { 51 if (j==n) return; j++; 52 change(1,1,cnt,a[j].l,a[j].r,1); 53 } 54 ans=min(ans,a[j].len-a[i].len); 55 change(1,1,cnt,a[i].l,a[i].r,-1); 56 } 57 } 58 59 int main() 60 { 61 scanf("%d%d",&n,&m); 62 for (i=1;i<=n;i++) 63 { 64 scanf("%d%d",&a[i].l,&a[i].r); 65 b[++cnt]=a[i].l,b[++cnt]=a[i].r; 66 a[i].len=a[i].r-a[i].l; 67 } 68 sort(a+1,a+n+1,cmp),sort(b+1,b+cnt+1); 69 for (i=1;i<=n;i++) a[i].l=find(1,cnt,a[i].l),a[i].r=find(1,cnt,a[i].r); 70 solve(); printf("%d\n",ans<INF?ans:-1); 71 return 0; 72 }
时间: 2024-10-05 23:26:50