安徽省省赛C:卡牌对决

问题 C: 卡牌对决

 上一题 正确率: 27.86%27.86% 下一题 

 "

时间限制33 秒/Second(s)内存限制512512 兆字节/Megabyte(s)
提交总数12311231正确数量343343
裁判形式标准裁判/Standard Judge我的状态已解决
难度分类标签贪心 排序

题目描述

有2N张牌,它们的点数分别为1到2N。Alice拿了其中的N张,Bob拿了剩下的N张. Alice和Bob会进行N轮游戏,在每轮游戏中,Alice 和Bob 各出一张牌。出了的牌不能收回。在前N/2轮中,每轮谁的牌点数大谁就赢;在后N/2轮中,每轮谁的牌点数小谁就赢。已知Bob 每一轮会出什么牌,试求Alice 最多能赢多少轮。
 

输入

第一行是一个整数N,
接下来N行,每行一个整数,表示Bob这轮会出什么。
2<=N <= 50000,保证N是偶数
 

输出

输出Alice最多能赢几轮
 

样例输入复制

4
1
8
4
3

样例输出复制

2

这一题有点像今年预选赛的一个题目,不过预选赛的比这个简单,这个题目我还调试了一会,我还是太菜了。

之前预选赛的那一题还是队友做出来的,不过我学会了如何处理这一类的题目,直接数组贪心就可以了,不需要想多麻烦。

这一题我是把它分为前半场和后半场来算的,先算后半场,将它后半场输入的数字按照从大到小的顺序排列,然后在数组1-N*2的数组中找也没有比他小的数,有就计数变量加一,否则说明之后后半场的数都没有比他小的;然后算前半场,将它前半场输入的数从大到小排序,然后在1-N*2的数组中找是否存在比他大的数,有则计数变量加一,否则说明前半场之后的数字也没有比他大的数。

最后输出计数变量即可。

代码如下:

#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>

typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50;

bool cmp(ll a, ll b)
{
    return a < b;
}
bool cmp2(ll a, ll b)
{
    return a > b;
}
ll a[N];
ll f[N];
void work()
{
    ll n,ans = 0;
    cin >> n;
    vector<ll>v,w;
    vector<ll>r;
    v.push_back(0);
    w.push_back(100001);
    r.push_back(0);
    for (int i = 1; i <= n; i++)
    {
        ll x;
        cin >> x;
        if(i <= n / 2)f[x] = 10, v.push_back(x);
        else f[x] = 20,w.push_back(x);
    }
    for (int i = 1; i <= n * 2; i++)
    {
        if (f[i] == 0)r.push_back(i);
    }
    sort(v.begin(), v.end());
    sort(r.begin(), r.end());
    sort(w.begin(), w.end(),cmp2);
    int p = r.size() / 2;
    int k = 0;
    for (int i : w)
    {
        if (k == 0)
        {
            k++;
            continue;
        }
        
        while (p > 0 && (r[p] > i || f[r[p]] != 0 ))p--;
        if (p < 1)break;
        f[r[p]] = 100;
        ans++;
        p--;
    }
    p = r.size()/ 2 + 1;
    k = 0;
    for (auto i : v)
    {
        if (k == 0)
        {
            k++;
            continue;
        }

        while (p < r.size() && (r[p] < i || f[r[p]] != 0))p++;
        if (p >= r.size())break;
        f[p] = 100;
        ans++;
        p++;
    }
    cout << ans << "\n";

}
int main()
{
    work();
    return 0;
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值