如有错误,请留言提醒,不要坑到小朋友
Input
6 3
1 5
2 1 7
3 1 3 8
Output
3
我们用小根堆来维护彩带的左端点,右端点就是堆中元素的最大值。由于题目给出的每一种小球的座标单调递增,所以很好求出每个球最近的下一个同类球是哪个。题目要求所有小球都必须在彩带上,就是说堆内的元素必须为K个,所以我们先将每种球的座标最小的放进堆里,并且记录初始答案,然后每次删除堆顶,为了维持堆里的元素个数,所以我们还要插入一个与删除元素相同种类的下一个球,就可更新答案了,当没有同种球可以插入时,就可以结束了。
在这里有人会有疑惑了,为什么这种球没了,不能改变其他的球来更新答案呢? 原因很简单,因为,插入其他的球,并不会改变堆顶,也就是说不会改变最小值,而只可能会让最大值变大,所以不可能在得到最优解。
还有人有疑惑,堆中元素的最大值怎么求呢? 其实,最大值就是所有进入过堆的元素的最大值,因为我们每次只将最小值删除,而不影响最大值,最大值是不断变大的。
总的时间复杂度为:O(NlogN),足以在一秒的时间内解决了。
#include<cstdlib>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxn 61
#define maxp 1000010
#define maxx 1000010
using namespace std;
typedef pair<int,int> PII;
inline int read(){
int tmp=0;char ch;
while(ch=getchar())if('0'<=ch&&ch<='9')break;
for(;'0'<=ch&&ch<='9';ch=getchar())tmp=tmp*10+ch-'0';
return tmp;
}
PII aa[maxx];
int tot,f[maxn],sum,n,k,ans=0x7fffffff;
priority_queue<PII,vector<PII>,greater<PII> >q;
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=k;i++){
int t=read();
for(int j=1;j<=t;j++){
int b=read();
aa[tot+j]=make_pair(b,i);
}
tot+=t;
}
// printf("%d\n",tot);
sort(aa+1,aa+tot+1);
for(int i=1;i<=tot;i++){
q.push(aa[i]);
if(!f[aa[i].second])sum++;
f[aa[i].second]=aa[i].first;
while(f[q.top().second]!=q.top().first)q.pop();
if(sum==k){ans=min(ans,aa[i].first-q.top().first);}
// printf("%d %d %d %d %d\n",ans,aa[i].first,aa[i].second,q.top().first,q.top().second);
}
printf("%d\n",ans);
// system("pause");
}
var
h,fir,e:array[0..60] of longint;
next,num,data:array[0..1000000] of longint;
n,k,tot,i,j,len,sum,a,ans,max:longint;
procedure ins(x,xx:longint);
var now,fa,t:longint;
begin
inc(len);
h[len]:=x;
e[len]:=xx;
now:=len;
fa:=now div 2;
while now>1 do
begin
if h[now]<h[fa] then
begin
t:=h[now]; h[now]:=h[fa]; h[fa]:=t;
t:=e[now]; e[now]:=e[fa]; e[fa]:=t;
now:=fa; fa:=fa div 2;
end
else
break;
end;
end;
procedure del;
var now,son,t:longint;
begin
h[1]:=h[len];
e[1]:=e[len];
dec(len);
now:=1;
while now<=len do
begin
if h[now*2]<h[now*2+1] then
son:=now*2
else
son:=now*2+1;
if (son<=len) and (h[now]>h[son]) then
begin
t:=h[now]; h[now]:=h[son]; h[son]:=t;
t:=e[now]; e[now]:=e[son]; e[son]:=t;
now:=son;
end
else
break;
end;
end;
begin
readln(n,k); tot:=0; len:=0; max:=0;
for i:=1 to k do
begin
read(sum);
inc(tot); read(data[tot]); fir[i]:=tot;
for j:=2 to sum do
begin
inc(tot); read(data[tot]);
next[tot-1]:=tot;
end;
end;
for i:=1 to k do
begin
ins(data[fir[i]],fir[i]);
if max<data[fir[i]] then
max:=data[fir[i]];
end;
ans:=max-h[1];
while true do
begin
if next[e[1]]=0 then break;
a:=e[1]; del; ins(data[next[a]],next[a]);
if max<data[next[a]] then max:=data[next[a]];
if ans>max-h[1] then
ans:=max-h[1];
end;
writeln(ans);
end.