zoukankan      html  css  js  c++  java
  • [51nod] 1494 选举拉票 #算法设计策略

    1494 选举拉票

    题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题

    现在你要竞选一个县的县长。你去对每一个选民进行了调查。你已经知道每一个人要选的人是谁,以及要花多少钱才能让这个人选你。现在你想要花最少的钱使得你当上县长。你当选的条件是你的票数比任何一个其它候选人的多(严格的多,不能和他们中最多的相等)。请计算一下最少要花多少钱。

    Input
    单组测试数据。
    第一行有一个整数n (1 ≤ n ≤ 10^5),表示这个县的选民数目。
    接下来有n行,每一行有两个整数ai 和 bi (0 ≤ ai ≤ 10^5; 0 ≤ bi ≤ 10^4),表示第i个选民选的是第ai号候选人,想要让他选择自己就要花bi的钱。
    你是0号候选人(所以,如果一个选民选你的话ai就是0,这个时候bi也肯定是0)。
    Output
    输出一个整数表示花费的最少的钱。
    Input示例
    5
    1 2
    1 2
    1 2
    2 1
    0 0
    Output示例
    3
    Analysis分析
    正解:算法设计策略 + 线段树
    为什么特别标上这个算法设计策略呢
    这道题思路实在太复杂qwq
    我们可以想象有多个河内塔,一个塔就是一个候选人,塔中一片就是一个选民,候选人的“决心”越大片越大
    因此我们这样排序:每个候选人的选票小票在上大票在下(笑)
    那么我们怎么抢票呢?
    宏观策略是这样的:抢票数最高的候选人最便宜的票
    因此就是从每个塔的顶端拿选票堆在自己的塔上,直到自己的塔最高
    所以这个东西想了我一个下午+一个晚上
    所以我最后去看题解了(听说CCZ和SXT是第四个和第五个AC的orz)
    题解的意思是这样:从大到小枚举最终得票数, 然后根据每次的不同选择计算出来的结果更新答案
    那么我枚举到自己有 i 张票的时候,需要保证其他候选人的票 < i
    所以他们多出来的票我就都收了(当然收的是最便宜的,这里用优先队列维护)
    砍完候选人的票之后,我的票可能仍然不够 i 张,定义我之前抢过来的票数为 num ,
    那么从票仓里再提取出 i - num + 投自己的最初的选票 张票即可
    当然这里是提取前 k 张最小的
    这里可以用权值线段树维护
    这样,我们从大到小枚举,因此枚举到第 i-1 张时,可以直接继承第 i 张的投票情况,无需初始化
    详情请看代码
    注意,票价是可以为 0 且不为自己选民的
     
    Code代码
     1 #include<stdio.h>
     2 #include<queue>
     3 #include<algorithm>
     4 #include<iostream>
     5 #define mid (L+R)/2
     6 #define lc (rt<<1)
     7 #define rc (rt<<1|1)
     8 #define maxn 200000
     9 using namespace std;
    10 
    11 long long n,list[maxn],qwq;
    12 bool vis[maxn];
    13 
    14 struct nodd{
    15     long long num,sum;
    16 }T[maxn*4];
    17 
    18 void modify(long long rt,long long L,long long R,long long pos,long long val){
    19     if(pos < L || pos > R) return;
    20     if(L == R) T[rt].num += val,T[rt].sum += val*pos;
    21     else{
    22         /*if(pos <= mid)*/ modify(lc,L,mid,pos,val);
    23         /*else*/ modify(rc,mid+1,R,pos,val);
    24         T[rt].num = T[lc].num+T[rc].num;
    25         T[rt].sum = T[lc].sum+T[rc].sum;
    26     }
    27 }
    28 
    29 long long query(long long rt,long long L,long long R,long long pos){
    30     if(pos <= 0) return 0;
    31     if(pos > T[rt].num) return 2e9;
    32     if(L == R) return L*pos;//T[rt].sum;
    33     else if(pos <= T[lc].num) return query(lc,L,mid,pos);
    34     else return T[lc].sum + query(rc,mid+1,R,pos-T[lc].num);
    35 }
    36 
    37 priority_queue<long long,vector<long long> ,greater<long long> > heap[maxn];
    38 
    39 bool cmp1(long long A,long long B){ return heap[A].size() > heap[B].size(); }
    40 
    41 int main(){
    42     scanf("%lld",&n);
    43     
    44     for(int i = 1;i <= n;i++){
    45         long long x,y;
    46         scanf("%lld%lld",&x,&y);
    47         heap[x].push(y);
    48         if(x&&!vis[x]) list[++qwq] = x,vis[x] = true;
    49         if(x) modify(1,0,20000,y,1);
    50     }
    51     
    52     sort(list+1,list+1+qwq,cmp1);
    53 //    cout << "list";
    54 //    for(int i = 1;i <= qwq;i++) printf("%d ",list[i]); cout << endl;
    55     long long s = heap[0].size(),num = 0,sum = 0,ans = 2e9;
    56     
    57     for(int i = n;i >= max(1LL,s);i--){
    58         for(int j = 1;j <= qwq;j++){
    59             if(heap[list[j]].size() < i) break;
    60             while(heap[list[j]].size() >= i){
    61                 sum += heap[list[j]].top();
    62                 modify(1,0,20000,heap[list[j]].top(),-1);
    63                 heap[list[j]].pop();
    64                 num++;
    65             }
    66         }ans = min(ans,sum+query(1,0,20000,i-(num+s)));
    67 //        printf("#%d: ans %d
    ",i,ans);
    68     }
    69     
    70     printf("%lld",ans);
    71     
    72     return 0;
    73 }
    高效算法设计策略
  • 相关阅读:
    模板 无源汇上下界可行流 loj115
    ICPC2018JiaozuoE Resistors in Parallel 高精度 数论
    hdu 2255 奔小康赚大钱 最佳匹配 KM算法
    ICPC2018Beijing 现场赛D Frog and Portal 构造
    codeforce 1175E Minimal Segment Cover ST表 倍增思想
    ICPC2018Jiaozuo 现场赛H Can You Solve the Harder Problem? 后缀数组 树上差分 ST表 口胡题解
    luogu P1966 火柴排队 树状数组 逆序对 离散化
    luogu P1970 花匠 贪心
    luogu P1967 货车运输 最大生成树 倍增LCA
    luogu P1315 观光公交 贪心
  • 原文地址:https://www.cnblogs.com/Chorolop/p/7761186.html
Copyright © 2011-2022 走看看