Grakn Forces 2020
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)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; }
template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; }
template<class T> void clear(T& a) { T().swap(a); }
const int N = 1e5 + 5;
int n, m, _, k;
int a[N], b[N], c[N], d[N];
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n;
rep (i, 1, n) cin >> a[i], d[i] = 0;
rep (i, 1, n) cin >> b[i];
rep (i, 1, n) cin >> c[i];
rep (i, 1, n) {
if (a[i] != d[i - 1] && d[i + 1] != a[i]) d[i + n] = d[i] = a[i];
else if (b[i] != d[i - 1] && d[i + 1] != b[i]) d[i + n] = d[i] = b[i];
else d[i + n] = d[i] = c[i];
}
rep (i, 1, n) cout << d[i] << ' ';
cout << '\n';
}
return 0;
}
B
贪心, 先不考虑 k, 则 a 数组完全等于 b_1
在考虑 k, a 数组有 m 个不相等的数, 则 b_1中有 m 个不相等的数
m <= k 直接出答案
m >= k, 那就使得, b_1 中 第 k 个数不同后, 都为 k
那么就使得 k - m 个数还未凑够
那就接着 b_2呗, 不过 你只能用 k - 1 个数了, 因为你的 b_1 前 m 个不同的数完全等于 a, 你的 b_2 这些位置必须为 0
你要用一个 0 来不干扰前面选好的, 所以是 k- 1
#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)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; }
template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; }
template<class T> void clear(T& a) { T().swap(a); }
const int N = 1e6 + 5;
int n, m, _, k;
int a[N] = {-1};
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n >> k; m = 0;
rep (i, 1, n) cin >> a[i], m += (a[i] != a[i - 1]);
if (k == 1 && m > 1) cout << -1 << '\n';
else if (k == 1 || m == 1) cout << 1 << '\n';
else cout << (m - 1 + k - 2) / (k - 1) << '\n';
}
return 0;
}
C
模拟
#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)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; }
template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; }
template<class T> void clear(T& a) { T().swap(a); }
const int N = 1e5 + 5;
int n, m, _, k;
ll a[N];
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n >> m;
rep(i, 1, n) cin >> a[i];
ll l = 1, r = n, c = 1, d = 1;
long double x = 0, y = m, t = 0;
while (1) {
if (l > r) {
t += (y - x) / (c + d); break;
}
long double t1 = (a[l] - x) / c, t2 = (y - a[r]) / d;
if (t1 == t2) t += t1, ++c, ++d, x = a[l++], y = a[r--];
else if (t1 < t2) t += t1, ++c, x = a[l++], y -= d * t1;
else t += t2, ++d, x += c * t2, y = a[r--];
}
cout << setiosflags(ios::fixed) << setprecision(15) << t << '\n';
}
return 0;
}
D
dp, f[i], 表示向上 i 步后, 最多向右 走几步
怎么转移呢?
先考虑正好走不出去的, 及 a[i] - c[j] == x, 则 f[x] = max(f[x], b[i] - d[j] + 1)
最后倒序 f[i] = max(f[i], f[i + 1]),
找答案就好了
#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)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; }
template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; }
template<class T> void clear(T& a) { T().swap(a); }
const int N = 1e6 + 5;
int n, m, _, k;
int a[N], b[N], c[N], d[N], f[N];
int main() {
IOS;
cin >> n >> m;
rep(i, 1, n) cin >> a[i] >> b[i];
rep(i, 1, m) cin >> c[i] >> d[i];
rep(i, 1, n)
rep(j, 1, m)
if (a[i] <= c[j] && b[i] <= d[j])
umax(f[c[j] - a[i]], d[j] - b[i] + 1);
int ans = 1e9;
per(i, 1e6, 0) umax(f[i], f[i + 1]), umin(ans, i + f[i]);
cout << ans;
return 0;
}
E
题意, m 个 数组, 每个数组里每两个数(x, y, x < y)会连一条边(x, y)
每个数组连的边的颜色是不同的, 对于每个数组我们可以删除一个数(有代价), 相当于把这个数组对 这个数建的边都删了
删除完某些数组中的某些数以后, 使得建的所有边, 连成的环中, 边的颜色必须一样(或者不存在环)
思考发现, 如果两个数组都含有 x, y , 那么已经有个环了, 且两条边颜色不一样, 所以我们要从这连个数组中的一个删去x或y
当然删除代价最小的, 所以我们先按照代价排序, 从高到低
维护并查集, 每个数属于哪个数组集合就好了, 两次就删掉这个数
#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)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; }
template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; }
template<class T> void clear(T& a) { T().swap(a); }
const int N = 1e5 + 5;
int n, m, _, k, t;
int a[N], b[N], f[N << 1], high[N << 1], tot;
pair<int, PII> edge[N << 1];
int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
bool unit(int x, int y) {
x = find(x), y = find(y);
if (x == y) return 0;
if (high[x] > high[y]) f[y] = x;
else if (high[x] < high[y]) f[x] = y;
else f[y] = x, ++high[x];
return 1;
}
int main() {
IOS; cin >> m >> n; tot = 0;
rep(i, 1, m) cin >> a[i];
rep(i, 1, n) cin >> b[i];
rep(i, 1, m) for (cin >> k; k; --k) cin >> t, edge[++tot] = {a[i] + b[t], { i, m + t }};
sort(edge + 1, edge + 1 + tot);
rep(i, 1, m + n) f[i] = i, high[i] = 1;
ll ans = 0;
per(i, tot, 1)
if (find(edge[i].se.fi) != find(edge[i].se.se)) unit(edge[i].se.fi, edge[i].se.se);
else ans += edge[i].fi;
cout << ans << '\n';
return 0;
}
F
反正没限制次数
最后最多两个不同的数, 无非是 [1, l] [l + 1, n] 这连个区间呗
什么情况可以一个数呢? 当然是 l - 1 + 1 == n - l - 1 + 1, 就是两个区长度相同
你操作 (1 + i, l + 1 + i) 并不就合并了吗?
由于 n 不一定是 2的次方, 所以操作一次 (1, \(2^{k}\) - 1) 一次 (n - \(2^{k}\) + 1, n) (\(2^{k}\) <= n && \(2^{k + 1}\) > n)
不就将 n 变成 \([1, n - 2^k] 和 [n - 2^k + 1, 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)
#define IOS ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef pair<ll, ll> PLL;
typedef vector<int> VI;
typedef double db;
template<class T1, class T2> bool umin(T1& a, T2 b) { return a > b ? (a = b, true) : false; }
template<class T1, class T2> bool umax(T1& a, T2 b) { return a < b ? (a = b, true) : false; }
template<class T> void clear(T& a) { T().swap(a); }
const int N = 1e5 + 5;
int n, m, _, k, t;
vector<PII> ans;
void solve(int l, int r) {
if (l == r) return;
int mid = (l + r) >> 1;
solve(l, mid); solve(mid + 1, r);
rep (i, l, mid) ans.pb({ i, i - l + 1 + mid });
}
int main() {
IOS; cin >> n;
m = 1 << (int)log2(n);
solve(1, 1 + m - 1); solve(n - m + 1, n);
cout << ans.size() << '\n';
for (auto i : ans) cout << i.fi << ' ' << i.se << "\n";
return 0;
}