[堆] Jzoj P5861 失意
题解
- 考虑对于一个交集,那么就是一条线段的右端点于一条线段的左端点的交集大小
- 则ans=min(右端点坐标)-max(左端点坐标)
- 考虑一种对于每个左端点统计答案的做法
- 我们把线段按照左端点从小到大排序,依次选择
- 每当选择一条线段,我们将它的右端点放进堆中
- 当堆中已有 m 个元素时
- 弹出最小的右端点减去当前左端点
代码
1 #include <cstdio> 2 #include <algorithm> 3 #include <queue> 4 #include <bitset> 5 using namespace std; 6 struct edge 7 { 8 int l,r,d; 9 bool operator <(edge b) const { return r>b.r; } 10 } e[1000005],head; 11 std:: priority_queue<edge>Q; 12 std:: bitset<1000005>visit,vis; 13 bool cmp(edge a,edge b) { return a.l==b.l?a.r<b.r:a.l<b.l; } 14 int num,n,m,tot,ans; 15 int main() 16 { 17 freopen("failure.in","r",stdin); 18 freopen("failure.out","w",stdout); 19 scanf("%d%d%d",&num,&n,&m); 20 for (int i=1;i<=n;i++) scanf("%d%d",&e[i].l,&e[i].r),e[i].d=i; 21 sort(e+1,e+n+1,cmp); 22 for (int i=1;i<=m;i++) Q.push(e[i]),++tot,visit[e[i].d]=1; 23 head=Q.top(),ans=max(head.r-e[m].l,0),vis=visit; 24 for (int i=m+1;i<=n;i++) 25 { 26 Q.push(e[i]),++tot,visit[e[i].d]=1; 27 if (tot>m) head=Q.top(),visit[head.d]=0,Q.pop(),tot--; 28 if (tot==m) 29 { 30 head=Q.top(); 31 int mx=max(0,head.r-e[i].l); 32 if (mx>=ans) ans=mx,vis=visit; 33 } 34 } 35 printf("%d\n",ans); 36 for (int i=1;i<=n;i++) if (vis[i]) printf("%d ",i); 37 }