T1 Voting (Hard Version) CF1251E2
为什么要贿赂选民给你投票!!!
题意:
主角需要获得 n n n个人的投票
有两种方式让某个人给他投票
- 已经投票的人数 > m >m >m
- 花 p p p枚硬币购买
分析:
对 m m m进行排序
保留前缀的 m m m数组, p r e [ x ] pre[x] pre[x]为 m m m小于等于 x x x的人数
对 x x x进行逆序处理,当枚举到 x x x的时候,假设 m m m小于等于 x − 1 x-1 x−1的那些人已经投票,也就是有 p r e [ x − 1 ] pre[x-1] pre[x−1]人已经投票
如果 p r e [ x − 1 ] ≥ x pre[x-1] \ge x pre[x−1]≥x那么不需要进行处理
如果 p r e [ x − 1 ] < x pre[x-1]<x pre[x−1]<x那么 m m m在 x x x到 n n n的人至少要收买 x − p r e [ x − 1 ] x-pre[x-1] x−pre[x−1]个人
得到所有 x x x需要收买的后缀,显然从后往前处理最优。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 7;
int pre[N];
vector<int>q[N];
multiset<int>se;//元素可重复且元素有序
int main() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int a, b;
scanf("%d %d", &a, &b);
pre[a]++;
q[a].push_back(b);
}
for (int i = 1; i <= n; i++)
pre[i] += pre[i - 1];
int cnt = 0;
ll ans = 0;
for (int i = n; i >= 1; i--) {
int len=q[i].size();
for (int j = 0; j < len; j++){
se.insert(q[i][j]);
}
int v = i - cnt - pre[i - 1];
while (v > 0) {
ans += (*se.begin());
se.erase(se.begin());
v--;
cnt++;
}
}
se.clear();
for (int i = 0; i <= n; i++) {
q[i].clear(), pre[i] = 0;
}
printf("%lld\n", ans);
return 0;
}
懂王也是胜选了,四年河东,四年河西,莫欺老人穷
T2 P2397 yyy loves Maths VI (mode)
一眼就能看出来是求众数,觉得很简单,但还是想了一会做法才切出来。
我们可以把所给数字分成两类:
一类是众数,一类是其他的数
根据题目所给条件,众数的数量一定严格大于其他数的数量。
如果我们使用每一个其他不同的数来抵消众数,那么抵消完毕之后,剩下的数一定全都是众数。
那么有了思路我们就来想想实现过程:
- 建一个变量 a n s ans ans存储当前找到的众数,建一个变量 c n t cnt cnt存储当前众数的数量
- 新加入一个数
- 如果和 a n s ans ans相同,即和当前找到的众数相同, c n t + + cnt++ cnt++
- 如果 c n t = 0 cnt=0 cnt=0,即没有找到众数,则把新数作为众数,即 a n s = ans= ans=新数, c n t = 1 cnt=1 cnt=1
- 如果不同,那么 c n t − − cnt-- cnt−−,即把当前的众数抵消掉一个
- 最后剩下来的 a n s ans ans就是众数
c o d e code code
#include<bits/stdc++.h>
using namespace std;
int n;
int ans,tot;//tot同cnt
int main()
{
scanf("%d",&n);
for