CF457C Elections
作者:互联网
一、题目
二、解法
感觉这道题贪心不太好做,考虑暴力一点的方法。
考虑从大到小枚举其他竞选人的最高票数,把超过的人的最便宜的选票买下来,这个是可以继承上一次的操作结果的,然后再看比枚举的最高票数差多少票,再买最便宜的票即可,这个可以用权值线段树维护。
时间复杂度O(nlogn),只讲了大体思路,具体写法看代码吧。
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#define up 10000
#define inf 0x3f3f3f3f
using namespace std;
const int M = 100005;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,m,k,sum,ans=inf,tr[M],s[M];
vector<int> g[M],h[M];
void ins(int i,int l,int r,int id,int f)
{//tr为个数,s为买下所有的钱数
tr[i]+=f;
if(l==r)
{
s[i]+=f*l;
return ;
}
int mid=(l+r)>>1;
if(mid>=id) ins(i<<1,l,mid,id,f);
else ins(i<<1|1,mid+1,r,id,f);
s[i]=s[i<<1]+s[i<<1|1];
}
int ask(int i,int l,int r,int k)
{
if(k==0) return 0;
if(l==r) return l*k;//注意要多少个才给多少个
int mid=(l+r)>>1;
if(tr[i<<1]>=k) return ask(i<<1,l,mid,k);
return s[i<<1]+ask(i<<1|1,mid+1,r,k-tr[i<<1]);
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
int a=read(),b=read();
g[a].push_back(b);
m=max(m,a);
if(!a) k++;
else ins(1,0,up,b,1);
}
for(int i=1;i<=m;i++)
{
sort(g[i].begin(),g[i].end());
reverse(g[i].begin(),g[i].end());
for(int j=0;j<g[i].size();j++)
h[j].push_back(g[i][j]);
}
for(int i=n;i>=0;i--)
{
for(int j=0;j<h[i].size();j++)
{
k++;
sum+=h[i][j];
ins(1,0,up,h[i][j],-1);
}
ans=min(ans,sum+ask(1,0,up,max(0,i-k+1)));
}
printf("%d\n",ans);
}
C202044zxy
发布了237 篇原创文章 · 获赞 12 · 访问量 5850
私信
关注
标签:CF457C,return,int,tr,Elections,while,flag,include 来源: https://blog.csdn.net/C202044zxy/article/details/104149008