Educational Codeforces Round 100 (Rated for Div. 2)
Educational Codeforces Round 100 (Rated for Div. 2)
A - Dungeon
贪心
int main() {
IOS;
for (cin >> _; _; --_) {
ll a, b, c; cin >> a >> b >> c;
ll d = (a + b + c) / 9 * 9;
if (d != a + b + c) cout << "NO\n";
else if (d / 9 > min(min(a, b), c)) cout << "NO\n";
else cout << "YES\n";
}
return 0;
}
B - Find The Array
每个b只含有一个二进制下的1, 必定相互之间可整除, 选择最接近 a[i] 的2的阶乘即可
或者还有一种解法 $a_1, 1, a_3, 1, ..., $ or \(1, a_2, 1, a_4, ...\) 这两个数组中必定有一个满足
ll solve(int x) {
ll m = 1e12, ans = -1;
rep (i , 0 , 29) {
ll b = 1ll << i;
if (abs(b - x) < m) m = abs(b - x), ans = b;
}
return ans;
}
int main() {
IOS;
for(cin >> _; _; --_) {
cin >> n ;
rep (i, 1, n) cin >> a[i];
rep (i, 1, n) cout << solve(a[i]) << " "; cout << '\n';
}
return 0 ;
}
C - Busy Robot
模拟完事
int main() {
IOS;
for (cin >> _; _; --_) {
cin>>n;;
rep (i, 1, n) cin >> t[i] >> pos[i];
t[n + 1] = 2e18;
ll R = 1,nowpos = 0, nowt = 1, ans = 0;
for (ll L = 1; L <= n; L = R) {
nowt = t[L]; R = L + 1;
while (R <= n && t[R] < nowt + abs(nowpos - pos[L])) {
ll tmp;
if (nowpos < pos[L]) tmp = nowt + (pos[R] - nowpos);
else tmp = nowt - (pos[R] - nowpos);
if (tmp >= t[R] && tmp <= min(nowt + abs(nowpos - pos[L]), t[R+1])) ++ans;
++R;
}
if (R == L + 1) ++ans;
nowpos = pos[L];
}
cout<< ans <<'\n';
}
return 0;
}
D - Pairs
先把给定的b序列排个序, 再从未选的集合里找能配对的数量(配n-x的, 和x的数量)
然后得出可以属于 x, 可以属于 n - x 的数量 ansl, ansr,
想想小学题, 全班n个人, a个会乒乓, b个会足球, 问多少人两个都会
这题是有 n 个数(b数组), ansl可以属于 x 对, ansr可以属于 n - x那一堆, 问多少个数可以属于二者
int main() {
IOS;
for (cin >> _; _; --_) {
cin >> n; rep (i, 1, n) cin >> a[i], v[a[i]] = 1;
int cnt = 0, ansl = 0, ansr = 0; sort(a + 1, a + n + 1);
rep (i, 1, n << 1) if(!v[i]) b[++cnt] = i, s.insert(i);
rep (i, 1, n) {
auto it = s.upper_bound(a[i]);
if (it == s.end()) continue;
else s.erase(it), ++ansl;
}
set<int>().swap(s);
rep (i, 1, n) s.insert(b[i]);
rep (i, 1, n) {
auto it = s.lower_bound(a[i]);
if (it == s.begin()) continue;
else s.erase(--it), ++ansr;
}
set<int>().swap(s);
rep (i, 1, n) v[a[i]] = 0;
cout << abs(ansl + ansr - n) + 1 << '\n';
}
return 0;
}
E - Plan of Lectures
这一眼就是拓扑排序, 关键是如何处理那 k 对数, 带权并查集不就好了?
int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
void unit(int x, int y) {
x = find(x);
if (x == y) return;
f[y] = x; sz[x] += sz[y]; ed[x] = ed[y];
}
int main() {
IOS; cin >> n >> k; vector<VI>(n + 1).swap(h);
rep(i, 0, n) f[i] = ed[i] = i;
rep(i, 1, n) {
cin >> a[i]; if (!a[i]) continue;
if (a[i] == i) return cout << 0, 0;
h[a[i]].pb(i); ++sz[i];
}
rep(i, 1, k) {
int a, b; cin >> a >> b;
if (ne[a] || pre[b]) return cout << 0, 0;
int nx = find(a), ny = find(b);
if (nx == ny) return cout << 0, 0;
ne[a] = b; pre[b] = a; unit(a, b);
}
rep(i, 1, n) if (f[i] == i) {
for (int j = i; j; j = ne[j]) {
int x = find(a[j]);
if (x == i) return cout << 0, 0;
for (auto y : h[j]) {
int fy = find(y);
if (fy == i) --sz[i], a[y] = 0;
}
}
}
queue<int> q; int ls = 0;
rep(i, 1, n) if (f[i] == i && !sz[i]) q.push(i);
while (!q.empty()) {
int x = q.front(); q.pop();
if (pre[x] || ne[ls]) return cout << 0, 0;
pre[x] = ls; ne[ls] = x; ls = ed[x];
for (int i = x; i; i = ne[i]) for (auto y : h[i]) {
y = find(y);
if (y != x && --sz[y] == 0) q.push(y);
}
}
int cnt = 0;
for (int i = ne[0]; i; i = ne[i]) ++cnt;
if (cnt != n) return cout << 0, 0;
for (int i = ne[0]; i; i = ne[i]) cout << i << ' ';
return 0;
}