貌似是套路题.
假设给定我们一些区间,那么这些区间交集的左端点是左端点最靠右区间的左端点.
所以我们将所有区间按照左端点从小到大排序,然后用堆维护前 k 大的右端点.
那么,对于枚举到的第 $i$ 个区间来说,右端点就是第 $k$ 大的右端点与当前区间右端点的较小值.
code:
#include <cstdio> #include <string> #include <cstring> #include <queue> #include <cctype> #include <algorithm> #define N 1000050 using namespace std; namespace IO { void setIO(string s) { string in=s+".in"; string out=s+".out"; freopen(in.c_str(),"r",stdin); } inline char nc() { static char buf[100000] , *p1 , *p2; return p1 == p2 && (p2 = (p1 = buf) + fread(buf , 1 , 100000 , stdin) , p1 == p2) ? EOF : *p1 ++ ; } inline int rd() { int ret = 0; char ch = nc(); while(!isdigit(ch)) ch = nc(); while(isdigit(ch)) ret = ((ret + (ret << 2)) << 1) + (ch ^ '0') , ch = nc(); return ret; } }; int n,k,ans,A[N]; struct node { int l,r,id; node(int l=0,int r=0,int id=0):l(l),r(r),id(id){} bool operator<(node b) const { return r>b.r; } }arr[N]; priority_queue<node>q; bool cmp(node a,node b) { return a.l<b.l; } int main() { // IO::setIO("input"); int i,j,mx=0; using namespace IO; n=rd(),k=rd(); for(i=1;i<=n;++i) { arr[i].l=rd(),arr[i].r=rd(); arr[i].id=i; } sort(arr+1,arr+1+n,cmp); for(i=1;i<=n;++i) { q.push(arr[i]); if(i<k) continue; else { if(i>k) q.pop(); node p=q.top(); mx=max(mx,min(arr[i].r,q.top().r)-arr[i].l); } } printf("%d\n",mx); while(!q.empty()) q.pop(); for(i=1;i<=n;++i) { if(i<k) q.push(arr[i]); else { node p=q.top(); q.push(arr[i]); if(i>k) q.pop(); int now=q.top().r-arr[i].l; if(now==mx) { int tot=0; while(!q.empty()) A[++tot]=q.top().id,q.pop(); sort(A+1,A+1+tot); for(i=1;i<=tot;++i) printf("%d ",A[i]); return 0; } } } return 0; }