51nod 1494 选举拉票 | 线段树
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 选举拉票 | 线段树的更多相关文章
- 51nod 1494 选举拉票 (线段树+扫描线)
1494 选举拉票 题目来源: CodeForces 基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 收藏 关注 现在你要竞选一个县的县长.你去对每一个选民进 ...
- 51nod 1364 最大字典序排列(线段树)
1364 最大字典序排列基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题 给出一个1至N的排列,允许你做不超过K次操作,每次操作可以将相邻的两个数交换,问能够得到的字 ...
- LightOJ 1370 Bi-shoe and Phi-shoe 欧拉函数+线段树
分析:对于每个数,找到欧拉函数值大于它的,且标号最小的,预处理欧拉函数,然后按值建线段树就可以了 #include <iostream> #include <stdio.h> ...
- loj1370(欧拉函数+线段树)
传送门:Bi-shoe and Phi-shoe 题意:给出多个n(1<=n<=1e6),求满足phi(x)>=n的最小的x之和. 分析:先预处理出1~1e6的欧拉函数,然后建立一颗 ...
- LOJ #2142. 「SHOI2017」相逢是问候(欧拉函数 + 线段树)
题意 给出一个长度为 \(n\) 的序列 \(\{a_i\}\) 以及一个数 \(p\) ,现在有 \(m\) 次操作,每次操作将 \([l, r]\) 区间内的 \(a_i\) 变成 \(c^{a_ ...
- 51nod 1463 找朋友(线段树+离线处理)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1463 题意: 思路: 好题! 先对所有查询进行离线处理,按照右区间排序, ...
- BZOJ 4034 树上操作(树的欧拉序列+线段树)
刷个清新的数据结构题爽一爽? 题意: 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x ...
- [BZOJ4026]dC Loves Number Theory 欧拉函数+线段树
链接 题意:给定长度为 \(n\) 的序列 A,每次求区间 \([l,r]\) 的乘积的欧拉函数 题解 考虑离线怎么搞,将询问按右端点排序,然后按顺序扫这个序列 对于每个 \(A_i\) ,枚举它的质 ...
- BZOJ 4034 [HAOI2015]树上操作(欧拉序+线段树)
题意: 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都增 ...
随机推荐
- Django中的Project和App的区别
Django是一个非常流行的用python编写的Web框架,在使用Django之前,我们需要了解一些基本的概念,这样可以在使用Django的时候对其有一个更加深入的把握.本文主要介绍Django中两个 ...
- c++ 使用this指针进行串联的函数调用
如代码所示,在每个成员函数函数体最后返回*this.即可实现串联调用. class Time { public: Time(, , ); Time &setHour(int); Time &a ...
- 小米6x抓包小程序https请求
1. charles安装证书,手机设置代理等这里不多讲了, 请进入下面链接查看详细 https://blog.csdn.net/manypeng/article/details/79475870 2. ...
- [ c++] cmake 编译时 undefined reference to `std::cout' 错误的解决方案
cmake .. 和 make 之后,出现如下错误 Linking CXX executable ../../../bin/ModuleTest CMakeFiles/ModuleTest.dir/ ...
- maven实战读书笔记(一)
环境变量设置 MAVEN_HOME:G:\maven-3.2\apache-maven-3.2.5 Path: G:\maven-3.2\apache-maven-3.2.5\bin 其实正确的设置应 ...
- Task 6.2冲刺会议九 /2015-5-22
今天把之前的跳转问题加以改正并加以优化.遇到的主要问题是跳转的时后时间有点长,以为没有成功.之后查资料说是端口没有及时释放,导致了程序的滞缓.明天要继续把程序的界面进行优化.
- SCRUM:第一、二天任务实现情况
在团队项目“广商百货”的SCRUM项目中我认领的任务: LOGO设计 5.18熬夜完成LOGO设计(投票通过): 设计理念: 1.全矢量图设计,适应各种超大尺寸使用: 2.3D化透视设计,简约视效,也 ...
- Git命令提交项目代码
Git客户端安装 今天就结合`GitHub`,通过`Git`命令,来了解如何实现开源代码库以及版本控制 GitHub是一个面向开源及私有软件项目的托管平台,因为只支持Git 作为唯一的版本库格式进行托 ...
- Linux内核0.11 makefile文件说明
# # if you want the ram-disk device, define this to be the # size in blocks. # 如果要使用 RAM 就定义块的大小(注释掉 ...
- 使用Shell脚本删除/清空日志文件
话不多少,直接上代码: #!/bin/bash workdir=("/home/Tax_Punish_Ret/log_txt") #可填写多个路径, 用空格隔开 # 查找日志文件 ...