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; }
相关文章推荐
- 【51nod】1494 选举拉票 扫描线+线段树
- 51nod 1494 选举拉票 | 线段树
- 51Nod-1494-选举拉票
- 51nod 1494 选举拉票&&cf458C
- [51nod] 1494 选举拉票 #算法设计策略
- 51nod 1672 区间交【线段树】【贪心】
- [枚举 线段树] 51Nod1494 选举拉票
- 51Nod 1672 扫描线 + 线段树/树状数组
- [HDOJ5091]Beam Cannon(贪心,线段树,扫描线,矩形内覆盖最多点)
- 【51Nod】1672 - 区间交(线段树 & 贪心)
- 【扫描线+贪心+线段树】Codeforces 458C Elections
- [51nod 1208] Stars in Your Window(线段树,扫描线)
- 51nod 1206 Picture 矩形周长求并 | 线段树 扫描线
- 51nod 1461 稳定桌【扫描线】【线段树】
- 51nod 1206 1028 1494题解+扫描线模板
- 51nod 1208 窗上的星星 | 线段树 扫描线
- 51Nod - 1559 线段树 + 扫描线
- 【51nod】1461 稳定桌 扫描线+线段树
- 【HDU 3255 Farming 】 线段树之扫描线(体积并)
- 51Nod 1091 线段的重叠(贪心+区间相关,板子题)