<贪心>ZJOI 2008 泡泡堂

可以交的题目链接1
可以交的题目链接2
QAQ贪心

先把两队人从大到小排一遍序
每次比较两队的队首和队尾(队首是本队最强的,队尾是本队最弱的)
最好的情况下(我方得分最多时)
①如果我方的队首大于对方的队首,用我方队首打败对方队首,显然最优
②我方的队尾大于对方队尾,说明我方所有的人都可以打败对方的队尾,所以消耗一个最弱的来打他,显然最优
③如果我方队首和队尾都比对方弱,(怎么着都得输一局),就用我队最弱的牵制对方最强的,这样会使最弱的人死得更有价值(23333)
④除了以上这些情况,只要任意一对平手或队首队尾都是平手,就让我方队尾去打对方队首,可以手推,三种情况中,这样都是最优的。

而对于最坏的情况,这里有一个小技巧,就是,用同样的方法求出对方最大可能获得的分数,因为每一局无论谁输谁赢或平手,两者的得分之和都是2,所以两队每次总的得分之和是2*n。因此,最坏情况下,我方的分是2*n–对方最好得分

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn=100010;
int n,ans[3];
int num[3][maxn];

bool cmp(int x,int y)
{
    return x>y;
}
void done(int k1,int k2)
{
    int mf=1,ml=n,tf=1,tl=n;
    for(int i=1;i<=n;++i)
    {
        if(num[k1][ml]>num[k2][tl])
        {
            ans[k1]+=2;
            ml--;
            tl--;
        }
        else if(num[k1][mf]>num[k2][tf])
        {
            ans[k1]+=2;
            mf++;
            tf++;
        }
        else 
        {
            if(num[k1][ml]==num[k2][tf]) ans[k1]++;
            ml--;
            tf++;
        } 
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%d",&num[1][i]);
    for(int i=1;i<=n;++i) scanf("%d",&num[2][i]);
    sort(num[1]+1,num[1]+n+1,cmp);
    sort(num[2]+1,num[2]+n+1,cmp);
    done(1,2);
    done(2,1);
    ans[2]=(n<<1)-ans[2];
    printf("%d %d",ans[1],ans[2]);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值