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
推式子,组合数学。
先选两个点,记横坐标之差为 ,则在长度为 的行内可以选出差值为 的点对有 对,两点分别可能在 列,所以这两点的行贡献为 。同理,列贡献为 。
还要在剩下的 个点中选 个点,则再乘上 ,则最终式子为:
#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
对顶堆。
利用绝对值的性质:
就是 的长度, 在 的左边或者 的右边,只会让答案变大。所以有 个 时,若 为偶数,则当 取为 时答案最小。反之则为 时最小.
则转化为经典题:动态维护第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);
}
}
}