1. 程式人生 > >[POI 2018] Prawnicy

[POI 2018] Prawnicy

getc lse max printf nbsp sin min struct priority

[題目鏈接]

https://www.lydsy.com/JudgeOnline/problem.php?id=5102

[算法]

首先,n條線段的交集一定是[Lmax,Rmin] , 其中,Lmax為最靠右的左端點,Rmin為最靠左的右端點

根據這個性質 , 我們不妨將所有線段按左端點為關鍵字排序 , 依次枚舉最終交集的左端點 , 同時 , 我們還需維護一個小根堆 , 維護前k大的右端點 , 每次我們通過( 堆頂 - 當前枚舉線段的左端點 )更新答案

[代碼]

#include<bits/stdc++.h>
using
namespace std; #define MAXN 1000010 struct segment { int id; int l,r; } a[MAXN]; int n,k,ans,l,r,len; priority_queue< pair<int,int> > q; int res[MAXN]; template <typename T> inline void read(T &x) { int f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if
(c == -) f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - 0; x *= f; } inline bool cmp(segment a,segment b) { if (a.l == b.l) return a.r > b.r; else return a.l < b.l; } int main() { read(n); read(k); for
(int i = 1; i <= n; i++) { a[i].id = i; read(a[i].l); read(a[i].r); } sort(a + 1,a + n + 1,cmp); ans = 0; for (int i = 1; i <= n; i++) { if ((int)q.size() < k) { q.push(make_pair(-a[i].r,a[i].id)); if ((int)q.size() == k) { ans = max(ans,-q.top().first - a[i].l); l = a[i].l; r = -q.top().first; continue; } } else { if (a[i].r < -q.top().first) continue; pair<int,int> tmp = q.top(); q.pop(); q.push(make_pair(-a[i].r,a[i].id)); if (-q.top().first - a[i].l > ans) { ans = -q.top().first - a[i].l; l = a[i].l; r = -q.top().first; } } } printf("%d\n",ans); if (ans == 0) { for (int i = 1; i <= k; i++) printf("%d ",i); printf("\n"); return 0; } for (int i = 1; i <= n; i++) { if (a[i].l <= l && a[i].r >= r) { res[++len] = a[i].id; if ((--k) == 0) break; } } for (int i = 1; i <= len; i++) printf("%d ",res[i]); printf("\n"); return 0; }

[POI 2018] Prawnicy