bzoj5102 [POI2018]Prawnicy
很基本的题目.
为了练习OOP,自己写个堆....
把所有区间按照左端点排个序,依次考虑左端点小于x的所有区间,在这些区间中找出最大的k个右端点,用堆维护就可以了.
调了一会儿.代码能力真是差啊.
#include<cstdio>
#include<algorithm>
using namespace std;
class interval{
public:
int l,r,num;
interval(){}
interval(int _l,int _r){
l=_l;r=_r;
}
bool operator <(const interval &B)const{
return r<B.r;
}
};
class heap{
private:
interval* v;
int sz,MEMSZ;
void expand(){
if(MEMSZ==0){
MEMSZ=100;sz=0;
v=new interval[MEMSZ];
}else{
interval* P= new interval[MEMSZ*2];
for(int i=1;i<=sz;++i)P[i]=v[i];
delete[] v;
v=P;MEMSZ=MEMSZ*2;
}
}
public:
heap(){
sz=0;MEMSZ=0;
}
int size(){
return sz;
}
void add(interval A){
if(sz+1>=MEMSZ)expand();
v[++sz]=A;
int y=sz;
while(y>1&&(v[y]<v[y>>1])){
swap(v[y],v[y>>1]);y>>=1;
}
}
void pop(){
if(sz==1)sz=0;
else{
swap(v[1],v[sz]);--sz;
int y=1;
while((y<<1)<=sz){
int p=(y<<1);
if((p+1)<=sz&&v[p+1]<v[p])p=p+1;
if(v[p]<v[y]){
swap(v[p],v[y]);
y=p;
}
else break;
}
}
}
void clear(){
delete[] v;
sz=MEMSZ=0;
}
int top(){
if(sz>=1)return v[1].r;
else return -1;
}
void Enum(){
for(int i=1;i<=sz;++i)printf("%d%c",v[i].num,(i==sz)?'\n':' ');
}
~heap(){
clear();
}
};
interval P[1000006];
bool cmp(const interval &a,const interval &b){
return a.l<b.l;
}
int ans=0,n,k;
void work(int flag){
heap a;
for(int i=1;i<k;++i){
a.add(P[i]);
}
for(int i=k;i<=n;++i){
a.add(P[i]);
while(a.size()>k){
a.pop();
}
int R=a.top();//printf(":%d %d\n",P[i].l,R);
if(R-P[i].l>ans){
ans=R-P[i].l;//printf("!%d\n",R-P[i].l);
}
if(flag&&R-P[i].l==ans){
a.Enum();return;
}
}
}
int main(){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i)scanf("%d%d",&P[i].l,&P[i].r),P[i].num=i;
sort(P+1,P+n+1,cmp);
work(0);
printf("%d\n",ans);
if(ans==0){
for(int i=1;i<=k;++i)printf("%d%c",i,(i==k)?'\n':' ');return 0;
}
work(1);
return 0;
}