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;
}
posted @ 2019-03-07 09:44  liu_runda  阅读(266)  评论(0编辑  收藏  举报
偶然想到可以用这样的字体藏一点想说的话,可是并没有什么想说的. 现在有了:文化课好难