51nod 1328 比赛往事

1328 比赛往事
1 秒 131,072 KB 80 分 5 级题
一个编程公开赛有 N 轮线上预选赛(N<=1000),将比赛编号为0,1,2,…,N-1。想参加这个公开赛的决赛,选手必须参加满所有N场比赛。对于第i场线上比赛,有个淘汰线cutoff[i],对于这场比赛排名在区间[1,cutoff[i]]的选手将通过这轮线上比赛,而排名大于cutoff[i]的被淘汰。一个选手只要一场线上比赛被淘汰就不能参加决赛。但是,被淘汰的人可以参加剩下没举办的线上比赛。(没错,你可能意识到了,决赛有概率根本没人能参加,事实就是如此。)现在你已经参加完了N场线上比赛,其中第i场比赛你的排名为place[i]。你现在有一项黑客技术,就是交换你的某两场比赛的排名,例如,place[i]=a,place[j]=b,你可以用你的这项技术使place[i]=b,place[j]=a。你只有这项技术,即只能交换两场不同比赛自己的排名,却不能修改、添加、删除比赛成绩。你可以任意次使用这个技术,让你能进入决赛,即交换若干次后使所有place[i]<=cutoff[i]。现在问题来了,你最少需要改变多少场比赛的成绩能让你进入决赛?如果一定进不了决赛输出-1,否则输出最少被改变的比赛场次。

提示:这个问题并不是询问最少交换多少次,而是最少有多少个场次参与了交换,比如你交换了place[1]与place[2],又交换了place[0]与place[3]虽然你只交换了2次,却改变了4个场次的成绩。
收起
输入
第一行一个整数 N,其中1<=N<=1000
之后N行,每行2个整数,分别代表 place[i] 与 cutoff[i],其中,1 <= place[i],cutoff[i] <= 1,000,000
输出
一行一个整数,即最少需要被改变的场次,当无法进决赛时输出-1.
输入样例
4
20 7500
100 2250
500 150
50 24
输出样例
3

思路:贪心。第一步可以确定p[i]>c[i]的是一定要进行交换的,所以p[i]>c[i]部分的值可以随意打乱,接下来贪心要做的就是对于每一个c[i],找到一个能与之匹配的值,首先要明白c[i]从小的开始匹配一定是最优的,因为大的c[i]放在后面给了其它数更多的替换空间,所以我们肯定想到了排序。因此,我们使用两个优先队列q1和q2维护c[i]和p[i],如果p[i]的top小于c[i]的top(),直接弹出两个top(),ans不加,否则ans+1,并到p[i]<=c[i]的部分去寻找一个p[i]

#include
using namespace std;
int n,tot;
struct node
{
    int x,y;
    node(int x=0,int y=0):x(x),y(y){}
    bool operator<(const node&o)const
    {
        return x,greater >q1,q2;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        if(x<=y) t[++tot].x=x,t[tot].y=y;
        else q1.push(x),q2.push(y);
    }
    sort(t+1,t+1+tot);
    int ans=q2.size();
    bool flag=true;
    while(!q2.empty())
    {
        int now=q2.top();q2.pop();
        if(q1.top()<=now)
        {q1.pop();continue;}
        else
        {
            ans++;
            int p=-1,ma=0;
            for(int i=1;i<=tot&&t[i].x<=now;i++)
            {
                if(vis[i]) continue;
                if(t[i].y>ma) ma=t[i].y,p=i;
            }
            if(p==-1||ma<=now)
            {
                flag=false;
                break;
            }
            q2.push(t[p].y);
            vis[p]=true;
        }
    }
    if(!flag) printf("-1\n");
    else printf("%d\n",ans);
}

你可能感兴趣的:(算法)