Codeforces Round #642 (Div. 3)
A
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef double db;
const int maxn = 1e5 + 5;
int n, m, _;
int a[maxn];
int main()
{
ios::sync_with_stdio(0); cin.tie(0);
for (cin >> _; _; --_)
{
cin >> n >> m;
if (n == 1) cout << 0 << '\n';
else if (n == 2) cout << m << '\n';
else cout << (m << 1) << '\n';
}
return 0;
}
B
贪心
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef double db;
const int maxn = 1e5 + 5;
int n, m, _;
int a[maxn], b[maxn];
int main()
{
ios::sync_with_stdio(0); cin.tie(0);
for (cin >> _; _; --_)
{
cin >> n >> m; a[0] = 0;
rep (i, 1, n) cin >> a[i], a[0] += a[i];
rep (i, 1, n) cin >> b[i];
sort(a + 1, a + 1 + n);
sort(b + 1, b + 1 + n);
rep (i, 1, m)
if (b[n + 1 - i] - a[i] > 0) a[0] += b[n + 1 - i] - a[i];
else break;
cout << a[0] << '\n';
}
return 0;
}
C
可以推公式 O(1), 但没必要直接O(n)
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef double db;
const int maxn = 2e5 + 5;
int n, m, _;
int a[maxn];
priority_queue<pair<int, PII>> q;
int main()
{
ios::sync_with_stdio(0); cin.tie(0);
for (cin >> _; _; --_)
{
cin >> n;
int a = n >> 1;
//cout << a << '\n';
ll sum = (ll)(1 + a) * a / 2;
rep (i, 1, a) sum += (ll)i * (i * 2 - 1);
cout << (sum << 2) << '\n';
}
return 0;
}
D
优先队列
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef double db;
const int maxn = 2e5 + 5;
int n, m, _;
int a[maxn];
priority_queue<pair<int, PII>> q;
int main()
{
ios::sync_with_stdio(0); cin.tie(0);
for (cin >> _; _; --_)
{
cin >> n; m = 0;
q.push({ n, { -1, n}});
while (m <= n && !q.empty())
{
int s = q.top().fi;
PII p = q.top().se; q.pop();
int mid = (-p.fi + p.se) >> 1;
a[mid] = ++m;
if (s == 1) continue;
if (mid != -p.fi) q.push({ mid + p.fi, {p.fi, mid - 1}});
q.push({ p.se - mid, { - mid - 1, p.se}});
}
rep (i, 1, n) cout << a[i] << ' ';
cout << '\n';
}
return 0;
}
E
吐了,卡了半天,结果是sum开小了,要两倍空间
划分子集,即 % k 余数相同
用dp
再第i个灯阶段
属于 c = i % k 子集, 选择 c 子集作为答案
f[c][0] 表示到i阶段, c子集所有灯关闭的最小步骤
f[c][1] 表示i阶段, 子集c中从某个 (d + b * k) 灯开始到 i灯全部打开的最小步骤
f[c][2] 表示i阶段, 子集c中从某个 (d + b * k) 灯 到 (x + y * k) 灯亮着, 让后到 i灯都灭着, 的最小步骤
转移方程
if (i - k < 0) d = sum[0];
else d = sum[i - k];
f[c][2] = min(f[c][2], f[c][1]) + sum[i] - d;
if (f[c][0] <= f[c][1]) f[c][1] = f[c][0] + sum[i - 1] - d;
else f[c][1] = f[c][1] + sum[i - 1] - d;
f[c][0] = sum[i];
if (s[i] == '0') ++f[c][1];
记得还要走完真个过程k, 所以走完n之后, 还要再走 rep(i, n + 1, n + k)
这就是为什么要sum要开两倍(其实不开也行)
#include <bits/stdc++.h>
#define all(n) (n).begin(), (n).end()
#define se second
#define fi first
#define pb push_back
#define mp make_pair
#define sqr(n) (n)*(n)
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef double db;
const int maxn = 1e6 + 5;
int n, m, _, k;
int a[maxn], sum[maxn << 1], f[maxn][3];
char s[maxn];
int main()
{
ios::sync_with_stdio(0); cin.tie(0);
for (cin >> _; _; --_)
{
cin >> n >> k >> s + 1;
rep(i, 0, k - 1) f[i][0] = 0, f[i][1] = f[i][2] = 1e9;
rep(i, 1, n)
{
sum[i] = sum[i - 1] + (s[i] == '1');
int c = i % k, d;
if (i - k < 0) d = sum[0];
else d = sum[i - k];
f[c][2] = min(f[c][2], f[c][1]) + sum[i] - d;
if (f[c][0] <= f[c][1]) f[c][1] = f[c][0] + sum[i - 1] - d;
else f[c][1] = f[c][1] + sum[i - 1] - d;
f[c][0] = sum[i];
if (s[i] == '0') ++f[c][1];
}
rep(i, n + 1, n + k)
{
sum[i] = sum[i - 1];
int c = i % k;
f[c][2] = min(f[c][2], f[c][1]) + sum[i] - sum[i - k];
if (f[c][0] <= f[c][1]) f[c][1] = f[c][0] + sum[i - 1] - sum[i - k];
else f[c][1] = f[c][1] + sum[i - 1] - sum[i - k];
f[c][0] = sum[i];
}
int ans = 2e9;
rep(i, 0, k - 1) ans = min(ans, min(f[i][0], min(f[i][1], f[i][2])));
cout << ans << '\n';
}
return 0;
}