51nod1494 选举拉票


题面

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

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

题解

啊……线段树……绝对要写完多检查一下……

不然会Debug De很久都De不出来……

长太息以掩涕兮……哀Bug之难De……

这道题和51nod的另一道题——稳定桌很相似。网上的题解把这类题归入“扫描线法”中。

具体做法:从大到小枚举你一共得到多少选票,然后分两步:选票比你多的人,你一定需要抢夺所有多出来的选票,当然,对每个人要抢他们手里最便宜的选票;如果抢完选票,当前选票数仍不够你枚举的选票数的话,就在所有不在你手中的选票中拣最便宜的抢。

注意抢夺选票这个过程是单向的,也就是你不可能把抢来的选票还回去。那么我们维护一个数据结构,支持求最小的k个数的和、支持删除一个数即可。我用的是线段树求第k大+树状数组求和。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
using namespace std;
typedef long long ll;
#define space putchar(' ')
#define enter putchar('\n')
#define INF 0x3f3f3f3f
template <class T>
bool read(T &x){
char c;
bool op = 0;
while(c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
else if(c == EOF) return 0;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
return 0;
}
template <class T>
void write(T x){
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
}
const int N = 200005;
struct people {
int a, b;
bool operator < (const people &obj) const{
return b < obj.b;
}
} peo[N];
int mx, n, ans = INF, adj[N], nxt[N], sze[N], pol[N];
int val[N], sum[4*N];
void add(int p, int x){
while(p <= n) val[p] += x, p += p & -p;
}
int ask(int p){
int ret = 0;
while(p) ret += val[p], p -= p & -p;
return ret;
}
void build(int k, int l, int r){
if(l == r) return (void)(sum[k] = 1);
int mid = (l + r) >> 1;
build(k << 1, l, mid);
build(k << 1 | 1, mid + 1, r);
sum[k] = sum[k << 1] + sum[k << 1 | 1];
}
void erase(int k, int l, int r, int p){
if(l == r) return (void)(sum[k] = 0);
int mid = (l + r) >> 1;
if(p <= mid) erase(k << 1, l, mid, p);
else erase(k << 1 | 1, mid + 1, r, p);
sum[k] = sum[k << 1] + sum[k << 1 | 1];
}
int query(int k, int l, int r, int p){
if(l == r) return l;
int mid = (l + r) >> 1;
if(sum[k << 1] >= p) return query(k << 1, l, mid, p);
else return query(k << 1 | 1, mid + 1, r, p - sum[k << 1]);
}
bool cmp(int a, int b){
return sze[a] < sze[b];
}
int main(){
read(n);
build(1, 1, n);
for(int i = 1; i <= n; i++)
read(peo[i].a), read(peo[i].b);
sort(peo + 1, peo + n + 1);
for(int i = n; i; i--){
nxt[i] = adj[peo[i].a];
adj[peo[i].a] = i;
sze[peo[i].a]++;
mx = max(mx, peo[i].a);
add(i, peo[i].b);
}
for(int i = 1; i <= mx; i++)
pol[i] = i;
sort(pol + 1, pol + mx + 1, cmp);
for(int tot = n, cost = 0, cnt = 0; tot >= 0; tot--){
for(int i = mx; i && sze[pol[i]] >= tot; i--)
for(int &e = adj[pol[i]]; e && sze[pol[i]] >= tot; e = nxt[e])
add(e, -peo[e].b), erase(1, 1, n, e), cost += peo[e].b, sze[pol[i]]--, cnt++;
if(cnt >= tot) ans = min(ans, cost);
else ans = min(ans, cost + ask(query(1, 1, n, tot - cnt)));
}
write(ans), enter;
return 0;
}

51nod 1494 选举拉票 | 线段树的更多相关文章

  1. 51nod 1494 选举拉票 (线段树+扫描线)

    1494 选举拉票  题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题  收藏  关注 现在你要竞选一个县的县长.你去对每一个选民进 ...

  2. 51nod 1364 最大字典序排列(线段树)

    1364 最大字典序排列基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 给出一个1至N的排列,允许你做不超过K次操作,每次操作可以将相邻的两个数交换,问能够得到的字 ...

  3. LightOJ 1370 Bi-shoe and Phi-shoe 欧拉函数+线段树

    分析:对于每个数,找到欧拉函数值大于它的,且标号最小的,预处理欧拉函数,然后按值建线段树就可以了 #include <iostream> #include <stdio.h> ...

  4. loj1370(欧拉函数+线段树)

    传送门:Bi-shoe and Phi-shoe 题意:给出多个n(1<=n<=1e6),求满足phi(x)>=n的最小的x之和. 分析:先预处理出1~1e6的欧拉函数,然后建立一颗 ...

  5. LOJ #2142. 「SHOI2017」相逢是问候(欧拉函数 + 线段树)

    题意 给出一个长度为 \(n\) 的序列 \(\{a_i\}\) 以及一个数 \(p\) ,现在有 \(m\) 次操作,每次操作将 \([l, r]\) 区间内的 \(a_i\) 变成 \(c^{a_ ...

  6. 51nod 1463 找朋友(线段树+离线处理)

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1463 题意: 思路: 好题! 先对所有查询进行离线处理,按照右区间排序, ...

  7. BZOJ 4034 树上操作(树的欧拉序列+线段树)

    刷个清新的数据结构题爽一爽? 题意: 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x ...

  8. [BZOJ4026]dC Loves Number Theory 欧拉函数+线段树

    链接 题意:给定长度为 \(n\) 的序列 A,每次求区间 \([l,r]\) 的乘积的欧拉函数 题解 考虑离线怎么搞,将询问按右端点排序,然后按顺序扫这个序列 对于每个 \(A_i\) ,枚举它的质 ...

  9. BZOJ 4034 [HAOI2015]树上操作(欧拉序+线段树)

    题意: 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增 ...

随机推荐

  1. RSA详解

    RSA RSA算法是第一个能同时用于加密和数字签名的算法,也易于理解和操作.RSA是被研究得最广泛的公钥算法,从提出到现今的三十多年里,经历了各种攻击的考验,逐渐为人们接受,普遍认为是目前最优秀的公钥 ...

  2. python中web应用与mysql数据库交互

    7使用数据库 具体使用python的DB-API,这一章里介绍如何编写代码与MYSQL数据库技术交互,这里使用一个通用的数据库API,名为DB-API. 7.1基于数据库的web应用 之前我们把日志数 ...

  3. 2018爆零记第二弹之day0

    话说初赛水了个70分,ε=(´ο`*)))唉,还是太菜了. 今天两点左右到了电子科大对面宾馆,收拾安顿好后又去电子科大踩点. 进门又走过了不长不短的水杉道,来到了不大不小的西湖(为什么是这个名字... ...

  4. 关于linux-centos7 安装完成git后npm突然无法使用问题处理

    报错: 解决方法: 查看一下nodejs是否安装,如果没有安装的话安装完成就能解决了

  5. 2017年第八届蓝桥杯【C++省赛B组】

    1.标题: 购物单 小明刚刚找到工作,老板人很好,只是老板夫人很爱购物.老板忙的时候经常让小明帮忙到商场代为购物.小明很厌烦,但又不好推辞. 这不,XX大促销又来了!老板夫人开出了长长的购物单,都是有 ...

  6. jQuery获取复选框选中的每一个值

    $('input[name="serviceMode"]:checked').each(function(){ this.attr('value') });

  7. “学霸系统”app——NABC

    “学霸系统”客户端项目是我们小组本次的课题. 一.需求(need) 对于这款软件,我们的目标是在手机端移植并实现网页端已有的用户管理.搜索.分类.上传下载.用户贡献与交互等功能,从而完成从PC到终端的 ...

  8. Tomcat提高并发

    Centos7环境下Tomcat 启动慢的解决方案1.增加熵值(本质增加random)安装软件 >> Yum –y install rng-tools 启动熵服务 >> Sys ...

  9. 第二阶段Sprint冲刺会议7

    进展:试着把视频录制功能加到时间提醒中,但是整合没有成功,今天没有进展.

  10. servlet的方法解析

    一般来说servlet继承了HttpServlet,我们可以覆盖某些方法来实现自己的功能. Init()和Init(ServletConfig config),我们一般只需覆盖后者,因为这个可以从se ...