收藏
关注
现在你要竞选一个县的县长。你去对每一个选民进行了调查。你已经知道每一个人要选的人是谁,以及要花多少钱才能让这个人选你。现在你想要花最少的钱使得你当上县长。你当选的条件是你的票数比任何一个其它候选人的多(严格的多,不能和他们中最多的相等)。请计算一下最少要花多少钱。
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
思路:
线段树+扫描线思想
实现代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const ll M = 1e5 + 10; vector<ll>g[M]; vector<ll>rk[M]; ll sum[M<<2],num[M<<2]; void pushup(ll rt){ num[rt] = num[rt<<1] + num[rt<<1|1]; sum[rt] = sum[rt<<1|1] + sum[rt<<1]; } void update(ll p,ll l,ll r,ll rt){ if(l == r){ sum[rt] += l; num[rt] ++; return ; } ll m = (l + r) >> 1; if(p <= m) update(p,lson); else update(p,rson); pushup(rt); } ll query(ll p,ll l,ll r,ll rt){ if(l == r) return l*p; ll m = (l + r) >> 1; if(p == num[rt<<1]) return sum[rt<<1]; else if(p < num[rt<<1]) return query(p,lson); else return sum[rt<<1] + query(p - num[rt<<1],rson); } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); ll n,u,v; ll mx = 0,ans = 0; cin>>n; for(ll i = 1;i <= n;i ++){ cin>>u>>v; if(v == 0) continue; ans += v; mx = max(mx,v); g[u].push_back(v); } for(ll i = 1;i <= M;i ++){ if(g[i].size()){ sort(g[i].begin(),g[i].end(),greater<ll>()); for(ll j = 0;j < g[i].size();j ++){ rk[j].push_back(g[i][j]); } } } ll nn = n; ll minn = ans,cnt = 0; for(ll i = 0;i < n;i ++){ nn -= rk[i].size(); if(rk[i].size()==0) continue; for(ll j = 0;j < rk[i].size();j ++){ ans -= rk[i][j]; update(rk[i][j],1,mx,1); } if(nn <= i+1){ cnt = query(min(n,i+2-nn),1,mx,1); } minn = min(minn,ans+cnt); } cout<<minn<<endl; }