zoukankan      html  css  js  c++  java
  • 51Nod 1494 选举拉票(权值线段树)

    http://www.51nod.com/Challenge/Problem.html#!#problemId=1494

    题解

    一开始有start个人投自己,num表示当前已经收买了多少人,从大到小枚举自己以i张票当选,那么其他人的票数一定要小于i,拿钱收买他们花费最少的>=i的这部分人,再加上另外要收买的i-start-num个最便宜收买的花费就是当前答案,这里可以对每个人的收买代价建立权值线段树来查找收买前i-start-num个最便宜的花费。注意不是选自己的选民可以选别人的时候叛变花费可能为0,所以线段树应该从0开始。

     1 #define dbg(x) cout<<#x<<" = "<< (x)<< endl
     2 #define IO std::ios::sync_with_stdio(0);
     3 #include <bits/stdc++.h>
     4 #define iter ::iterator
     5 using namespace  std;
     6 typedef long long ll;
     7 typedef pair<ll,ll>P;
     8 #define pb push_back
     9 #define se second
    10 #define fi first
    11 #define rs o<<1|1
    12 #define ls o<<1
    13 const ll inf=0x7fffffff;
    14 const int N=1e5+10;
    15 int M;
    16 priority_queue<ll,vector<ll>,greater<ll> >q[N];
    17 int id[N],vis[N],cnt;
    18 ll start;
    19 bool cmp(ll x,ll y){
    20     return q[x].size()>q[y].size();
    21 }
    22 struct node{
    23     ll num,sum;
    24 }a[N*4];
    25 void push(int o){
    26     a[o].num=a[ls].num+a[rs].num;
    27     a[o].sum=a[ls].sum+a[rs].sum;
    28 }
    29 void up(int o,int l,int r,int p,ll v){
    30     if(l==r){
    31         a[o].num+=v;
    32         a[o].sum+=v*l;
    33         return;
    34     }
    35     int m=(l+r)/2;
    36     if(p<=m)up(ls,l,m,p,v);
    37     else up(rs,m+1,r,p,v);
    38     push(o);
    39 }
    40 ll qu(int o,int l,int r,int p){
    41     if(p<=0)return 0;
    42     if(a[1].num<p)return 2e9;
    43     if(l==r)return 1ll*l*p;
    44     int m=(l+r)/2;
    45     if(p<=a[ls].num)return qu(ls,l,m,p);
    46     else return a[ls].sum+qu(rs,m+1,r,p-a[ls].num);
    47 }
    48 int main(){
    49     scanf("%d",&M);
    50     for(int i=1;i<=M;i++){
    51         ll x,y;
    52         scanf("%lld%lld",&x,&y);
    53         if(!x){
    54             start++;
    55             continue;
    56         }
    57         q[x].push(y);
    58         up(1,0,50000,y,1);
    59         if(!vis[x]){
    60             id[++cnt]=x;
    61             vis[x]=1;
    62         }
    63     }
    64     sort(id+1,id+1+cnt,cmp);
    65     ll ans=1e18,res=0,num=0;
    66     for(int i=M;i>=max(1ll,start);i--){
    67         for(int j=1;j<=cnt;j++){
    68             int x=id[j];
    69             if(q[x].size()<i)break;
    70             while(q[x].size()>=i){
    71                 ll y=q[x].top();
    72                 res+=y;
    73                 up(1,0,50000,y,-1);
    74                 q[x].pop();
    75                 num++;
    76             }
    77         }
    78         ll r=qu(1,0,50000,i-num-start);
    79         ans=min(ans,res+r);
    80     }
    81     printf("%lld
    ",ans);
    82 }
  • 相关阅读:
    uinty实现玩家尾随鼠标位置平滑旋转角度
    matlab hornerDemo
    【App 开发框架
    mobiscroll手机端插件 好用(时间、日历、颜色)
    朴素的UNIX之-调度器细节
    String与StringBuffer的差别
    用jquery ajax做的select菜单,选中的效果
    Codeforces Round #253 (Div. 2)A. Anton and Letters
    unix环境高级编程——文件i/o
    CSDN的技术问题
  • 原文地址:https://www.cnblogs.com/ccsu-kid/p/10755017.html
Copyright © 2011-2022 走看看