辩论

辩论

时间限制: 1 Sec 内存限制: 128 MB

题目描述

一场辩论会开始了,这场辩论会上有两个议题 1 , 2 1,2 1,2
N N N 个参加辩论的候选人,每个人对这两个议题都有明确的态度,支持或反对。
作为组织者,小 D D D 认真研究了每个候选人,并给每个人评估了一个非负的活跃度,他想让活跃度之和尽可能大。
但是,由于一些不可抗力,选出的候选人必须满足以下两个条件:

  1. 至少有一半的人支持议题 1 1 1(如果是奇数上取整)。
  2. 至少有一半的人支持议题 2 2 2

D D D 想知道,在满足以上两个条件的情况下,活跃度之和最大是多少。

输入

第一行一个整数 N N N,描述辩论会的候选人。
接下来 N N N 行,每行描述一个候选人的态度和活跃度,由一个长度为 2 2 201串和一个整数 A i A_i Ai组成。01 串中第 i i i 位为 0 0 0 表示反对第 i i i 个议题,为 1 1 1 表示支持, A i A_i Ai描述活跃度。

输出

一行一个整数,表示辩论会最大的活跃度。

样例输入

【样例1】

6
11 6
10 4
01 3
00 3
00 7
00 9

【样子2】

6
11 19
10 22
00 18
00 29
11 29
10 28

样例输出

【样例1】

22

【样子2】

105

提示

对于 100 % 100\% 100% 的数据, N ≤ 4 × 1 0 5 , 0 ≤ A i ≤ 5 × 1 0 3 N≤4×10^5,0≤A_i≤5×10^3 N4×105,0Ai5×103

思路

  • 11 11 11 肯定是能选的

  • 01 01 01 10 10 10 排序,从大到小一对一对的选

  • 剩下的 01 01 01 10 10 10 00 00 00 从大到小选直到不符合条件

#pragma GCC optimize(3,"Ofast","inline")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <set>
#include <map>
#include <cmath>
#include <queue>
#include <algorithm>
#include <unordered_map>
#include <vector>
using namespace std;
#define ls (rt<<1)
#define rs (rt<<1|1)
typedef long long ll;
template <typename T>
inline void read(T &x) {
    x = 0;
    static int p;
    p = 1;
    static char c;
    c = getchar();
    while (!isdigit(c)) {
        if (c == '-')p = -1;
        c = getchar();
    }
    while (isdigit(c)) {
        x = (x << 1) + (x << 3) + (c - 48);
        c = getchar();
    }
    x *= p;
}
template <typename T>
inline void print(T x) {
    if (x<0) {
        x = -x;
        putchar('-');
    }
    static int cnt;
    static int a[50];
    cnt = 0;
    do {
        a[++cnt] = x % 10;
        x /= 10;
    } while (x);
    for (int i = cnt; i >= 1; i--)putchar(a[i] + '0');
    puts("");
}
const int mod = 1e9+9;
const int inf = 0x3f3f3f3f;
const int maxn = 4e5+10;
vector<int>a,b,c,d;
int n,sum,num;
char s[10];
ll ans;
inline void work() {
    scanf("%d", &n);
    for (int i = 1, x; i <= n; i++) {
        scanf("%s%d", s, &x);
        if (s[0] == '1' && s[1] == '1') {
            ans += x;
            sum++;
            num++;
        }
        if (s[0] == '0' && s[1] == '1') a.emplace_back(x);
        if (s[0] == '1' && s[1] == '0') b.emplace_back(x);
        if (s[0] == '0' && s[1] == '0') c.emplace_back(x);
    }
    sort(a.begin(), a.end(), greater<int>());
    sort(b.begin(), b.end(), greater<int>());
    int mi = min(a.size(), b.size());
    for (int i = 0; i < mi; i++) {
        ans += a[i] + b[i];
        num++;
        sum += 2;
    }
    for (int i = mi; i < a.size(); i++) d.emplace_back(a[i]);
    for (int i = mi; i < b.size(); i++) d.emplace_back(b[i]);
    for (int i = 0; i < c.size(); i++) d.emplace_back(c[i]);
    sort(d.begin(), d.end(), greater<int>());
    for (int i = 0; i < d.size(); i++) {
        if (num * 2 < sum+1) break;
        ans += d[i];
        sum++;

    }
    print(ans);
}
int main() {
    //freopen("1.txt","r",stdin);
    int T = 1;
    //read(T);
    while (T--) {
        work();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值