您的位置:首页 > 其它

51nod 1494 选举拉票【贪心】【扫描线】【线段树】

2017-10-24 17:11 357 查看

Description

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

题解

直接做很困难,所以我们想到了枚举我的选票数,所有选票数比我多的人的选票都要被我抢到小于我的选票数(一定是从小到大抢),这样抢来以后,不一定选票数达到了我枚举的选票数,所以我就需要从所有剩下的选票中选出一些来补上,这样就变成了求全局的前k小(可以直接用线段树),枚举的时候就是扫描线从大到小枚举,所有选票数比我多的人的选票中被我选出来的都要从线段树中删除。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#define maxn 100006
#define maxm 10006
using namespace std;
inline char nc(){
static char buf[100000],*i=buf,*j=buf;
return i==j&&(j=(i=buf)+fread(buf,1,100000,stdin),i==j)?EOF:*i++;
}
inline int _read(){
char ch=nc();int sum=0;
while(!(ch>='0'&&ch<='9'))ch=nc();
while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
return sum;
}
struct data{
int l,r,num,sum;
}tree[maxm*4];
int n,m,top,ans,a[maxn],stack[maxn];
bool vis[maxn];
priority_queue<int,vector<int> ,greater<int> > heap[maxn];
void build(int p,int l,int r){
tree[p].l=l;tree[p].r=r;
if(l>=r)return;
int mid=(l+r)>>1;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);
}
void update(int p,int t,int k){
if(tree[p].l>t||tree[p].r<t)return;
if(tree[p].l==tree[p].r){
tree[p].num+=k;tree[p].sum+=k*t;return;
}
update(p<<1,t,k);update(p<<1|1,t,k);
tree[p].num=tree[p<<1].num+tree[p<<1|1].num;
tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum;
}
int query(int p,int k){
if(k<=0)return 0;
if(k>tree[p].num)return 2e9;
if(tree[p].l==tree[p].r)return tree[p].l*k;
if(k<=tree[p<<1].num)return query(p<<1,k);
return tree[p<<1].sum+query(p<<1|1,k-tree[p<<1].num);
}
bool cmp(int x,int y){return heap[x].size()>heap[y].size();}
int main(){
freopen("nineteen.in","r",stdin);
freopen("nineteen.out","w",stdout);
n=_read();
build(1,0,10000);
memset(vis,1,sizeof(vis));
for(int i=1,x,y;i<=n;i++){
x=_read(),y=_read(),heap[x].push(y);
if(x&&vis[x])a[++m]=x,vis[x]=0;
if(x)update(1,y,1);
}
sort(a+1,a+1+m,cmp);
ans=2e9;int s=heap[0].size(),sum=0,num=0;
for(int i=n;i>=max(1,s);i--){
for(int j=1;j<=m;j++){
if(heap[a[j]].size()<i)break;
while(heap[a[j]].size()>=i)sum+=heap[a[j]].top(),update(1,heap[a[j]].top(),-1),heap[a[j]].pop(),num++;
}
ans=min(ans,sum+query(1,i-num-s));
}
printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: