CF 457C Elections 解題報告(線段樹)

C. Elections
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

You are running for a governor in a small city in Russia. You ran some polls and did some research, and for every person in the city you know whom he will vote for, and how much it will cost to bribe that person to vote for you instead of whomever he wants to vote for right now. You are curious, what is the smallest amount of money you need to spend on bribing to win the elections. To win elections you need to have strictly more votes than any other candidate.

Input

First line contains one integer n (1 ≤ n ≤ 105) — number of voters in the city. Each of the next n lines describes one voter and contains two integers ai and bi (0 ≤ ai ≤ 105; 0 ≤ bi ≤ 104) — number of the candidate that voter is going to vote for and amount of money you need to pay him to change his mind. You are the candidate 0 (so if a voter wants to vote for you, ai is equal to zero, in which case bi will also be equal to zero).

Output

Print one integer — smallest amount of money you need to spend to win the elections.

Sample test(s)
input
5
1 2
1 2
1 2
2 1
0 0
output
3
input
4
1 2
1 2
2 1
0 0
output
2
input
1
100000 0
output
0

    解題報告: 昨晚(準確來說是今天早上)CF上的比賽第三題。前兩題1小時多搞定了,這題一直沒有想法。比賽後就去睡了。白天看了前幾名的代碼,然後就有點頭緒了。

    我們的目標是用最少的錢使自己的票數多餘其他人的票數。我們可以直接買票比我們當前票數多的那些人的票,這樣我們的票增加了,他們的票減少了;我們也可以直接買最便宜的票,直到超過所有其他人。這樣我們可以枚舉最後其他人的票最多有多少。減少的票我們都買下來,不夠我們就繼續買最便宜的。最終取結果的最小值。

    代碼如下:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <iomanip>
using namespace std;
#define ff(i, n) for(int i=0;i<(n);i++)
#define fff(i, n, m) for(int i=(n);i<=(m);i++)
#define dff(i, n, m) for(int i=(n);i>=(m);i--)
#define fit(it, n) for(auto it = (n).begin(); it != (n).end(); it++)
#define bit(n) (1LL<<(n))
typedef long long LL;
typedef unsigned long long ULL;
void work();
int main()
{
#ifdef ACM
    freopen("in.txt", "r", stdin);
#endif // ACM
    work();
}

/***************************************************/

#define lson l, m, pos<<1
#define rson m+1, r, pos<<1|1
const int maxn = 111111;
int num[maxn<<2];
int pri[maxn<<2];

int p[maxn], si[maxn];

bool cmp(int a, int b)
{
    return si[a] > si[b];
}

void updateFather(int pos)
{
    num[pos] = num[pos<<1] + num[pos<<1|1];
    pri[pos] = pri[pos<<1] + pri[pos<<1|1];
}

void update(int p, int x, int l = 0, int r = 10000, int pos = 1)
{
    if (l == r)
    {
        num[pos] += x;
        pri[pos] += x * p;

        return;
    }

    int m = (l+r)/2;
    if (p <= m)
        update(p, x, lson);
    else
        update(p, x, rson);

    updateFather(pos);
}

int query(int k, int l = 0, int r = 10000, int pos = 1)
{
    if (k == 0) return 0;
    if (l == r) return pri[pos]/num[pos]*k;
    if (k == num[pos]) return pri[pos];

    int m = (l+r)/2;
    if (k <= num[pos<<1])
        return query(k, lson);
    else
        return pri[pos<<1] + query(k-num[pos<<1], rson);
}

void work()
{
    int n;
    while (scanf("%d", &n) == 1)
    {
        memset(num, 0, sizeof(num));
        memset(pri, 0, sizeof(pri));

        map<int, multiset<int>> vote;
        ff (i, n)
        {
            int a, b;
            scanf("%d%d", &a, &b);
            if(a) vote[a].insert(b);
            update(b, 1);
        }

        int L = 0;
        fit (it, vote)
        {
            p[L++] = it->first;
            si[it->first] = it->second.size();
        }
        sort(p, p+L, cmp);

        int ans = 2e9;
        int vnum = 0, vsum = 0;
        int end = 0;
        dff(i, n, 1)
        {
            while(end < L && si[p[end]] >= i) end ++;
            ff(j, end)
            {
                auto it = vote[p[j]].begin();
                int price = *it;
                vnum ++;
                vsum += price;
                update(price, -1);
                vote[p[j]].erase(it);
            }
            ans = min(ans, vsum + query(max(i-vnum, 0)));
        }

        printf("%d\n", ans);
    }
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章