[cf193c]Students' Revenge解题报告

题意:
有 n 条命令,你要从中选出恰好 p 条命令作为候选命令,然后主席会从中选出恰好 k 条命令执行。
每条命令有两个属性:如果执行那么主席的会变白的头发数 Ai,如果不执行那么委员会的不满意指数 Bi 。
对于主席来说,她首先希望不执行的那 p-k 条给委员会带来的不满意指数最小,然后希望那 k 条命令使自己变白的头发最少。
对于你来说(,由于某些原因),你首先希望主席变白的头发最多,然后希望委员会的不满意指数最大。
现在让你求应该选出哪 p 条命令。

显然主席肯定会以B为第一关键字升序以A为第二关键字降序选p-k个不执行,然后执行剩下的。
所以说只要倒着在n-(p-k)个里面选k个A最大的,如果有一样的就选靠后的,然后从最靠前的开始再选p-k个即可。
写这题的时候犯了好多傻逼错误:
①一定要耐着性子给自己出一些极限小数据和极限大数据,不要急功近利。。
②用pair的时候一定要想清楚第二关键字的比较方式,尤其是在你其实不需要第二关键字比较的时候。。
代码:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
#include<algorithm>
struct MS{
    int a,b,i;
    bool operator < (const MS & o)const{
        return b!=o.b?b<o.b:a>o.a;
    }
}a[100005];
inline void in(int &x){
    char c=getchar();
    while(c<'0'||c>'9')c=getchar();
    x=0;
    for(;c>='0'&&c<='9';c=getchar())x=x*10+(c^'0');
}
pair<int,int> heap[100005];
int k;
inline void up(int now){
    for(int next=now>>1;next&&heap[next]>heap[now];now=next,next>>=1)swap(heap[now],heap[next]);
}
inline void down(int now){
    for(int next=now<<1;next<=k;now=next,next<<=1){
        if(next<k&&heap[next+1]<heap[next])++next;
        //cout<<"Down:"<<now<<","<<next<<endl;
        if(heap[now]<heap[next])return;
        swap(heap[now],heap[next]);
    }
}
int main(){
    //freopen("cf193c.in","r",stdin);
    //freopen("cf193c.out","w",stdout);
    int n,p,i;
    in(n),in(p),in(k);
    for(i=1;i<=n;++i)in(a[i].a),in(a[i].b),a[i].i=i;
    sort(a+1,a+n+1);
    pair<int,int> tmp;
    int Min=n-k+1;
    for(i=k;i--;)heap[i+1]=make_pair(a[n-i].a,a[n-i].i);
    for(i=k;i;--i)down(i);
    /*for(int i=1;i<=k;++i)cout<<heap[i].first<<","<<heap[i].second<<" "; puts("");*/
    for(i=n-k,p-=k;i>p;--i){
        if(heap[1].first<(tmp=make_pair(a[i].a,a[i].i)).first){
            //cout<<"Get:"<<a[i].a<<","<<a[i].i<<endl;
            Min=i;
            heap[1]=tmp;
            down(1);
        }
        /*cout<<a[i].a<<","<<a[i].i<<endl;
        for(int i=1;i<=k;++i)cout<<heap[i].first<<","<<heap[i].second<<" ";
        puts("");*/
    }
    /*for(int i=1;i<=k;++i)cout<<heap[i].first<<","<<heap[i].second<<" ";
    puts("");*/
    printf("%d",heap[k].second);
    while(--k)printf(" %d",heap[k].second);
    for(;p;--p)printf(" %d",a[--Min].i);
}

你可能感兴趣的:(堆)