AtCoder Beginner Contest 127
AtCoder Beginner Contest 127
https://atcoder.jp/contests/abc127/tasks
4/6: ABCD
A - Ferris Wheel
水题
#include <bits/stdc++.h>
using namespace std;
int main () {
int a, b;
cin >> a >> b;
if (a <= 5) cout << 0;
else if (a <= 12) cout << b / 2;
else cout << b;
}
B - Algae
水题
#include <bits/stdc++.h>
using namespace std;
int main () {
int r, d, ans;
cin >> r >> d >> ans;
for (int i = 1; i <= 10; i++) {
ans = r * ans - d;
cout << ans << endl;
}
}
C - Prison
差分
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
int a[N], n, m, ans;
int main () {
cin >> n >> m;
for (int i = 0; i < m; i++) {
int l, r;
cin >> l >> r;
a[l] ++, a[r+1] --;
}
for (int i = 1; i <= n; i++) a[i] += a[i-1];
for (int i = 1; i <= n; i++) {
//cout << a[i] << ' ';
if (a[i] == m) ans ++;
}
cout << ans;
}
D - Integer Cards
二分
关键在于最终局面是固定的,所以每次贪心的把小的变为最大的。排序然后二分,二分边界不断右移是因为p数组降序排列之后保证了后面查找的都只会更小。
#include <bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int, int> pii;
const int N = 1e5 + 5;
int a[N], n, m, ans;
pii p[N];
signed main () {
cin >> n >> m;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= m; i++) cin >> p[i].second >> p[i].first;
sort (p + 1, p + m + 1, greater<pii>());
sort (a + 1, a + n + 1);
int st = 1;
//for (int i = 1; i <= n; i++) cout << a[i] << ' ';cout << endl;
for (int i = 1; i <= m; i++) {
int val = p[i].first, cnt = p[i].second;
int pos = lower_bound (a + st, a + n + 1, val) - a;
int len = pos - st; //[st, pos-1]变为val
//cout << st << ' ' << pos << endl;
ans += min (len, cnt) * val;
st += min (len, cnt);
//cout << st << ' ' << pos << endl;
}
ans += a[st];
while (st <= n) ans += a[++st];
cout << ans << endl;
}
//每次把最小的小于ci的bi个数字变为ci
//终局是固定的
E - Cell Distance
推式子,组合数学。
先选两个点,记横坐标之差为 \(d_x=|x_1-x_2|\),则在长度为 \(n\) 的行内可以选出差值为 \(d_x\) 的点对有 \(n-d_x\) 对,两点分别可能在 \(m\) 列,所以这两点的行贡献为 \(d_x\times(n-d_x)\times m^2\)。同理,列贡献为 \(d_y\times(m-d_y)\times n^2\)。
还要在剩下的 \(n\times m-2\) 个点中选 \(k-2\) 个点,则再乘上 \(C_{n\times m-2}^{k-2}\),则最终式子为:
\[(\sum_{i=1}^{n-1}i\times(n-i)\times m^2 + \sum_{i=1}^{m-1}i\times(m-i)\times n^2)\times C_{n\times m-2}^{k-2}
\]
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 200005, mod = 1000000007;
int fact[N], infact[N], ans;
int qmi(int a, int k, int p) {
int ans = 1;
while (k) {
if (k & 1) ans = ans * a % p;
k >>= 1;
a = a * a % p;
}
return ans;
}
void init() {
fact[0] = infact[0] = 1;
for (int i = 1; i <= N - 3; i++) {
fact[i] = fact[i - 1] * i % mod;
infact[i] = infact[i - 1] * qmi (i, mod - 2, mod) % mod;
}
}
int C(int a, int b) {
return fact[a] * infact[a - b] % mod * infact[b] % mod;
}
signed main () {
init ();
int n, m, k;
cin >> n >> m >> k;
for (int i = 1; i < n; i++) ans += (i * (n - i) * m * m) % mod;
for (int i = 1; i < m; i++) ans += (i * (m - i) * n * n) % mod;
ans = (ans % mod * C (n * m - 2, k - 2)) % mod;
cout << ans << endl;
}
F - Absolute Minima
对顶堆。
利用绝对值的性质:
\(|x-a|+|x-b|\) 就是 \(ab\) 的长度,\(x\) 在 \(a\) 的左边或者 \(b\) 的右边,只会让答案变大。所以有 \(cnt\) 个 \(a\) 时,若 \(cnt\) 为偶数,则当 \(x\) 取为 \(a_{\frac{cnt}2}\) 时答案最小。反之则为 \(a_{\frac{cnt}2+1}\)时最小.
则转化为经典题:动态维护第k小
#include <bits/stdc++.h>
#define int long long
using namespace std;
priority_queue <int> big; //大根堆堆顶即中位数
priority_queue <int, vector<int>, greater<int>> small;
signed main () {
int q, sum = 0;
cin >> q;
while (q --) {
int op;
cin >> op;
if (op == 2) cout << big.top () << ' ' << sum << endl;
else {
int a, b; cin >> a >> b;
sum += b, small.push (a), big.push (a);
int ss = small.top (), bb = big.top ();
small.pop (), big.pop ();
if (ss < bb) sum += bb - ss, swap (ss, bb);
small.push (ss), big.push (bb);
}
}
}