【NOIP2018 模拟赛04.14】 陪审团

这里写图片描述


题解:

–这道题其实是 贪心 吧,我们先来分析一波:
1.对于每个s和t,一定有(s-t)个人被甲选了,却没有被乙选上,而他们没有被选上的原因是:y值比那t个被选中的人的y的最小值还要小,或是y值相等时x太大
2.假设我们要让一个(x1,y1)的人被乙选上,那么那(s-t)个人的y值都要比y1小,或是与y1相等,x比x1大
3.所以说如果比某个人的y值小(或是y值相等时x比他大)的人数不足(s-t)个的话,他是显然不可能被乙选上的
–现在我们就可以先把必定不可能的人标记出来,再让甲选t个可能被乙选中且x值最大的前t个人,最后找(s-t)个满足条件的人充数就行了

–我们就可以用强大的sort来解决问题了,啦啦啦


代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=1e5+5;

int n,s,t;
int x[MAXN],y[MAXN];
int sx[MAXN],sy[MAXN],S[MAXN];
bool no[MAXN],choose[MAXN];
long long ansx,ansy;

bool comp1(const int &a,const int &b){
    if(x[a]!=x[b])
        return x[a]>x[b];
    return y[a]>y[b];
}

bool comp2(const int &a,const int &b){
    if(y[a]!=y[b])
        return y[a]>y[b];
    return x[a]<x[b];
}

bool comp3(const int &a,const int &b){
    if(no[a]!=no[b])
        return no[a];
    if(y[a]!=y[b])
        return y[a]>y[b];
    return x[a]>x[b];
}

int main(){
    cin>>n>>s>>t;
    for(int i=1;i<=n;i++){
        scanf("%d%d",&x[i],&y[i]);
        sx[i]=i;
        sy[i]=i;
        S[i]=i;
    }
    sort(sx+1,sx+1+n,comp1);
    sort(sy+1,sy+1+n,comp2);
    for(int i=n;i>=n-(s-t)+1;i--)
        no[sy[i]]=1;
    int sum=0;
    for(int i=1;i<=n;i++){
        if(!no[sx[i]]){
            choose[sx[i]]=1;
            sum++;
            if(sum==t)
                break;
        }
    }
    for(int i=n;i>=1;i--){
        if(choose[sy[i]])
            break;
        else
            no[sy[i]]=1;
    }
    sort(S+1,S+1+n,comp3);
    for(int i=1;i<=s-t;i++)
        choose[S[i]]=1;
    for(int i=1;i<=n;i++){
        if(choose[i]){
            ansx+=x[i];
            ansy+=y[i];
        }
    }
    cout<<ansx<<" "<<ansy;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41709770/article/details/79975150