不可能都讲,都挺水的,讲几道我觉得有意思的
E 距离
题意
每次操作修改一对关系,问所有关系的最值
大概思路
有点像莫队的思想,用一个神奇的map迭代器就能过。
代码
void solve(){
int n, m;
std::cin >> n >> m;
std::map<std::pair<int, int>, int> f;
std::map<int, int> cnt;
while (m--) {
int op, a, b, c;
std::cin >> op >> a >> b >> c;
if (op == 1) {
cnt[f[{a, b}]]--;
if (cnt[f[{a, b}]] == 0) cnt.erase(f[{a, b}]);
f[{a, b}] += c;
cnt[f[{a, b}]]++;
} else {
cnt[f[{a, b}]]--;
if (cnt[f[{a, b}]] == 0) cnt.erase(f[{a, b}]);
f[{a, b}] -= c;
cnt[f[{a, b}]]++;
}
std::cout << cnt.rbegin()->first << "\n";//rbegin()取最大值,begin()取最小值
}
}
H 考试
题意
给定等长度数组a,b,可以做任意次操作,将数组a的某个元素值增加,求最小的增加量总和,使得满足 $a[i] > b[i]$ 的i个数严格大于满足 $a[i] < b[i]$ 的i个数。
大概思路
一个有趣的贪心,模拟一下就过了
代码
void solve(){
int n;
std::cin >> n;
std::vector<int> a(n), b = a;
for (auto &i : a) std::cin >> i;
for (auto &i : b) std::cin >> i;
std::vector<int> c;
int win = 0;//胜
int fail = 0;//负
int ping = 0;//平
for (int i = 0; i <n; i++) {
if (a[i] > b[i]) win++;
else if (a[i] == b[i]) ping++;
else {
c.push_back(b[i] - a[i]);
fail++;
}
}
std::sort(c.begin(), c.end());
i64 sum = 0;
int i = 0;
while (win <= fail) {
if (ping) {//贪心选择平局,因为平局只要花费1的代价就能让fail-win的值减1
ping--;
win++;
sum++;
} else {//贪心地指增到刚好能让fail减少1的程度,构造一个平局,留给上面进行下一轮贪心
//(为什么不干脆顺便加1?因为有可能这里fail--后就可以退出while循环了,没必要再加1使win++)
fail--;
ping++;
sum += c[i++];
}
}
std::cout << sum;
}