題意簡述
給你 個區間 ,選出 恰好 個,使得交集最大。輸出最長的長度和方案。
注:區間 的長度被定義爲 。
。
思路框架
若干的區間的交集,顯然,左端點是所有左端點的最大值,右端點是所有右端點的最小值。
然後我們枚舉左端點的最大值。怎麼枚舉呢?按左端點從小到大排序,枚舉到 表示只能用 之前的區間。那麼所有的左端點就都 了。
然後這個時候我們怎麼選最大值呢?
- 我們只能在 中選
- 選擇 個使得最小值最大
怎麼選擇 個使得最小值最大呢?那肯定是從大到小排序之後選前 個啊!然後這時候最大的最小值,就是從大到小之後排第 位的數。那麼我們現在就是要支持動態插入(無刪除)的第 大。可以用對頂堆做。
對頂堆如何做
維護一個小根堆(堆頂是最小值),和一個大根堆(堆頂是最大值)。我們默認把數字插入到小根堆中,如果小根堆中的數字個數 ,那麼我們把小根堆中的 最小值 放到大根堆裏。
那麼有一個顯然易證的性質:大根堆中的所有數,任何時候都 小根堆中的所有數。也就是,大根堆的堆頂 小根堆的堆頂。
而且我們還保證了小根堆中只有 個數。那麼這 個數 當前的其它所有數,顯然,這 個數字就是前 大。求出這 個數中的最小值(小根堆頂),就是當前的第 大。
這個辦法也可以用於求中位數 (也就是 不一定靜態,單調遞增的情況也可以求)
代碼
#include <bits/stdc++.h>
using namespace std;
namespace Flandre_Scarlet
{
#define N 1666666
#define F(i,l,r) for(int i=l;i<=r;++i)
#define D(i,r,l) for(int i=r;i>=l;--i)
#define Fs(i,l,r,c) for(int i=l;i<=r;c)
#define Ds(i,r,l,c) for(int i=r;i>=l;c)
#define MEM(x,a) memset(x,a,sizeof(x))
#define FK(x) MEM(x,0)
#define Tra(i,u) for(int i=G.Start(u),v=G.To(i);~i;i=G.Next(i),v=G.To(i))
#define p_b push_back
#define sz(a) ((int)a.size())
#define all(a) a.begin(),a.end()
#define iter(a,p) (a.begin()+p)
int I()
{
int x=0;char c=getchar();int f=1;
while(c<'0' or c>'9') f=(c=='-')?-1:1,c=getchar();
while(c>='0' and c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return (x=(f==1)?x:-x);
}
void Rd(int cnt,...)
{
va_list args; va_start(args,cnt);
F(i,1,cnt) {int* x=va_arg(args,int*);(*x)=I();}
va_end(args);
}
struct node{int l,r,id;} a[N];
bool operator<(node a,node b){return a.l<b.l;}
int n,k;
void Input()
{
Rd(2,&n,&k);
F(i,1,n) a[i]=(node){I(),I(),i};
}
priority_queue<int,vector<int>,greater<int> > Q1; // 小根堆
priority_queue<int> Q2; // 大根堆
void Soviet()
{
sort(a+1,a+n+1);
int Max=-0x3f3f3f3f,l,r;
F(i,1,n)
{
Q1.push(a[i].r);
if (sz(Q1)>k)
// 其實這裏理論上應該是個 while 循環
// 然而實際上我們每次只會新加入一個數,那麼 sz(Q1) 頂多等於 k+1,彈一次即可
// 寫中位數的話,這裏要改成 while !
{
Q2.push(Q1.top()); Q1.pop();
}
if (i>=k) // 這裏注意判一下 i>=k,很重要,會出錯! (我就掛在這的QaQ
{
int rr=Q1.top(),ll=a[i].l;
if (rr-ll>Max)
{
Max=rr-ll; l=ll; r=rr;
}
}
}
printf("%d\n",Max);
int cnt=0;
F(i,1,n)
{
if (a[i].l<=l and r<=a[i].r)
{
printf("%d ",a[i].id);
++cnt;
}
if (cnt==k) break;
}
}
#define Flan void
Flan IsMyWife()
{
Input();
Soviet();
}
}
int main()
{
Flandre_Scarlet::IsMyWife();
getchar();getchar();
return 0;
}