Codeforces Global Round 5

Contest Info


[Practice Link](https://codeforces.com/contest/1237)
Solved A B C1 C2 D E F G H
5/9 O O O O O - - - -
  • O 在比赛中通过
  • Ø 赛后通过
  • ! 尝试了但是失败了
  • - 没有尝试

Solutions


A. Balanced Rating Changes

题意:
给出\(n\)个数\(a_i\),保证\(\sum a_i = 0\),现在需要将每个数变成\(\left \lfloor \frac{a_i}{2} \right\rfloor\)或者\(\left\lceil \frac{a_i}{2} \right\rceil\),使得变化之后的所有数之和还是\(0\)

思路:
考虑全都变成\(\left \lfloor \frac{a_i}{2} \right\rfloor\),然后差了多少补上即可。

代码:

view code
#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl "\n" 
using namespace std;
using db = double;
using ll = long long;
using ull = unsigned long long; 
using pII = pair <int, int>;
using pLL = pair <ll, ll>;
constexpr int mod = 1e9 + 7;
template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; } 
template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
inline int rd() { int x; cin >> x; return x; }
template <class T> inline void rd(T &x) { cin >> x; }
template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }  
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0) 
void err() { cout << "\033[39;0m" << endl; } 
template <class T, class... Ts> void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A> 
void err(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; err(args...); }
inline void pt() { cout << endl; } 
template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << ' '; pt(args...); }
template <template<typename...> class T, typename t, typename... A> 
void pt(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; pt(args...); }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
//head
constexpr int N = 1e6 + 10;
int n, a[N]; 
void run() {
	for (int i = 1; i <= n; ++i) cin >> a[i];
	vector <int> vec;
	ll tot = 0; 
	for (int i = 1; i <= n; ++i) {
		if (a[i] % 2 == 0) {
			a[i] /= 2;
		} else {
			if (a[i] > 0) {
				a[i] /= 2;
				++a[i];
			} else 
				a[i] /= 2;
			vec.push_back(i); 
		}
		tot += a[i];
	}
	while (tot) {
		a[vec.back()]--;
		vec.pop_back();
		--tot;
	}
	for (int i = 1; i <= n; ++i)
		pt(a[i]);
	
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);
	cout << fixed << setprecision(20);
	while (cin >> n) run();
	return 0;
}

B. Balanced Tunnel

题意:
有一个山洞,有一辆车,给出进入山洞的顺序和出山洞的顺序,计算发生了多少超车事件。

思路:
转化成每辆车进入山洞的时间和出山洞的时间,那么一辆车被另一辆车超了当且仅当这辆车进入山洞的时间比另一辆车早,出山洞的时间比另一辆车晚。

代码:

view code
#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl "\n" 
using namespace std;
using db = double;
using ll = long long;
using ull = unsigned long long; 
using pII = pair <int, int>;
using pLL = pair <ll, ll>;
constexpr int mod = 1e9 + 7;
template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; } 
template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
inline int rd() { int x; cin >> x; return x; }
template <class T> inline void rd(T &x) { cin >> x; }
template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }  
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0) 
void err() { cout << "\033[39;0m" << endl; } 
template <class T, class... Ts> void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A> 
void err(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; err(args...); }
inline void pt() { cout << endl; } 
template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << ' '; pt(args...); }
template <template<typename...> class T, typename t, typename... A> 
void pt(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; pt(args...); }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
//head
constexpr int N = 1e5 + 10;
int n; pII a[N];  
void run() {
	for (int i = 1; i <= n; ++i) {
		a[rd()].fi = i;
	}
	for (int i = 1; i <= n; ++i) {
		a[rd()].se = i;
	}
	sort(a + 1, a + 1 + n, [&](pII x, pII y) { return x.fi < y.fi; });
	int Max = 0, res = 0;
	for (int i = 1; i <= n; ++i) {
		if (Max > a[i].se) ++res;
		chmax(Max, a[i].se);
	}
	pt(res);
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);
	cout << fixed << setprecision(20);
	while (cin >> n) run();
	return 0;
}

C1. Balanced Removals (Easier)

题意:
三维空间中给出\(n\)个点,\(n\)是偶数,每次选择两个点拿走,能拿走的情况当且仅当这两个点形成的立方体中不存在还没被拿走的点。

思路:
\(n\)很小,枚举一个点,再对这个点找一个曼哈顿距离最小的点拿走。
时间复杂度\(O(n^2)\)

代码:

view code
#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl "\n" 
using namespace std;
using db = double;
using ll = long long;
using ull = unsigned long long; 
using pII = pair <int, int>;
using pLL = pair <ll, ll>;
constexpr int mod = 1e9 + 7;
template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; } 
template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
inline int rd() { int x; cin >> x; return x; }
template <class T> inline void rd(T &x) { cin >> x; }
template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }  
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0) 
void err() { cout << "\033[39;0m" << endl; } 
template <class T, class... Ts> void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A> 
void err(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; err(args...); }
inline void pt() { cout << endl; } 
template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << ' '; pt(args...); }
template <template<typename...> class T, typename t, typename... A> 
void pt(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; pt(args...); }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
//head
constexpr int N = 2e3 + 10, INF = 0x3f3f3f3f;
int n, x[N], y[N], z[N], vis[N];
int getdis(int a, int b) {
	return abs(x[a] - x[b]) + abs(y[a] - y[b]) + abs(z[a] - z[b]);
}
void run() {
	memset(vis, 0, sizeof vis);
	for (int i = 1; i <= n; ++i) cin >> x[i] >> y[i] >> z[i];
	vector <pII> res;
	for (int i = 1; i <= n; ++i) {
		if (vis[i]) continue;
		int pos = -1, dis = INF;
		for (int j = 1; j <= n; ++j) {
			if (vis[j] || i == j) continue;
			if (getdis(i, j) < dis) {
				dis = getdis(i, j);
				pos = j;
			}
		}
		res.push_back(pII(i, pos));
		vis[i] = vis[pos] = 1;
	}
	for (auto &it : res)
		pt(it.fi, it.se);
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);
	cout << fixed << setprecision(20);
	while (cin >> n) run();
	return 0;
}

C2. Balanced Removals (Harder)

题意:
同C1

思路:
先按一维排序,然后将这一维相同的按第二维排序,再将第二维相同的按第三维排序,然后取两个排序后相邻的拿掉。
时间复杂度\(O(nlogn)\)

代码:

view code
#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl "\n" 
using namespace std;
using db = double;
using ll = long long;
using ull = unsigned long long; 
using pII = pair <int, int>;
using pLL = pair <ll, ll>;
constexpr int mod = 1e9 + 7;
template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; } 
template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
inline int rd() { int x; cin >> x; return x; }
template <class T> inline void rd(T &x) { cin >> x; }
template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }  
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0) 
void err() { cout << "\033[39;0m" << endl; } 
template <class T, class... Ts> void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A> 
void err(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; err(args...); }
inline void pt() { cout << endl; } 
template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << ' '; pt(args...); }
template <template<typename...> class T, typename t, typename... A> 
void pt(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; pt(args...); }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
//head
constexpr int N = 1e5 + 10;
int n;
vector <pII> res;
struct E {
	int x[3], id;
	E() {}
};
void gao(vector <E> &vec, int p) {
	if (vec.size() == 1) return;
	sort(vec.begin(), vec.end(), [&](E a, E b) { return a.x[p] < b.x[p]; });
	vector <vector<E>> now;
	for (auto &it : vec) {
		if (now.empty()) {
			vector<E> tmp;
			tmp.push_back(it);
			now.push_back(tmp);
		} else {
			if (it.x[p] == now.back().back().x[p]) {
				now.back().push_back(it);
			} else {
				vector<E> tmp;
				tmp.push_back(it);
				now.push_back(tmp);
			}
		}
	}
	for (auto &it : now) gao(it, p + 1);
	vec.clear();
	for (auto &it : now) {
		if (!it.empty()) {
			assert(it.size() == 1);
			vec.push_back(it.back());
		}
	}	
	while (vec.size() >= 2) {
		E u = vec.back(); vec.pop_back();
		E v = vec.back(); vec.pop_back();
		res.emplace_back(u.id, v.id);
	}
}
void run() {
	vector <E> e(n);
	for (int i = 0; i < n; ++i) {
		cin >> e[i].x[0] >> e[i].x[1] >> e[i].x[2];
		e[i].id = i + 1;
	}
	res.clear();
	gao(e, 0);
	for (auto &it : res)
		pt(it.fi, it.se);
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);
	cout << fixed << setprecision(20);
	while (cin >> n) run();
	return 0;
}

D. Balanced Playlist

题意:
给出\(n\)个数,它是一个无限长的序列,\(n\)是循环节。
现在对于每个位置\(i \in [1, n]\)询问至少要往后走多少个数,使得期间的最大值大于最后一个数的两倍。

思路:
先将序列复制一遍,并容易发现答案不会超过\(2n\)
然后求出\(f[i]\)表示在这个数前面并且离这个数最近的并且比当前这个数大\(2\)倍的数的下标。
那么我们对于一个\(i\),可以二分答案\(mid\),当且仅当\(f[i], i \in [i, i + mid]\)的最大值大于等于\(i\)

代码:

view code
#pragma GCC optimize("Ofast,unroll-loops,no-stack-protector,fast-math")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <bits/stdc++.h>
#define fi first
#define se second
#define endl "\n" 
using namespace std;
using db = double;
using ll = long long;
using ull = unsigned long long; 
using pII = pair <int, int>;
using pLL = pair <ll, ll>;
constexpr int mod = 1e9 + 7;
template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; } 
template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
inline int rd() { int x; cin >> x; return x; }
template <class T> inline void rd(T &x) { cin >> x; }
template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }  
#define dbg(x...) do { cout << "\033[32;1m" << #x << " -> "; err(x); } while (0) 
void err() { cout << "\033[39;0m" << endl; } 
template <class T, class... Ts> void err(const T& arg, const Ts&... args) { cout << arg << ' '; err(args...); }
template <template<typename...> class T, typename t, typename... A> 
void err(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; err(args...); }
inline void pt() { cout << endl; } 
template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << ' '; pt(args...); }
template <template<typename...> class T, typename t, typename... A> 
void pt(const T <t> &arg, const A&... args) { for (auto &v : arg) cout << v << ' '; pt(args...); }
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
//head
constexpr int N = 5e5 + 10, M = 25;
int n, a[N], b[N << 1], f[N], res[N];
struct BIT {
	int a[N];
	void init() { memset(a, 0, sizeof a); }
	void update(int x, int v) {
		for (; x > 0; x -= x & -x)
			chmax(a[x], v);
	}
	int query(int x) {
		int res = 0;
		for (; x < N; x += x & -x)
			chmax(res, a[x]);
		return res;
	}
}bit;
struct RMQ {
	int Max[N][M];
	int mm[N];
	void init(int n, int *b) {
		mm[0] = -1;
		for (int i = 1; i <= n; ++i) {
			mm[i] = ((i & (i - 1)) == 0) ? mm[i - 1] + 1 : mm[i - 1];
			Max[i][0] = b[i];
		}
		for (int j = 1; j <= mm[n]; ++j) {
			for (int i = 1; i + (1 << j) - 1 <= n; ++i) {
				Max[i][j] = max(Max[i][j - 1], Max[i + (1 << (j - 1))][j - 1]);
			}
		}
	}
	int queryMax(int x, int y) {
		int k = mm[y - x + 1];
		return max(Max[x][k], Max[y - (1 << k) + 1][k]);
	}
}rmq;
void run() {
	bit.init();
	for (int i = 1; i <= n; ++i) cin >> a[i];
	for (int i = n + 1; i <= n * 2; ++i) a[i] = a[i - n];
	for (int i = n * 2 + 1; i <= n * 3; ++i) a[i] = a[i - n];
	*b = 0;
	for (int i = 1; i <= n; ++i) b[++*b] = a[i], b[++*b] = a[i] * 2 + 1; 
	sort(b + 1, b + 1 + *b);
	*b = unique(b + 1, b + 1 + *b) - b - 1;
	for (int i = 1; i <= n * 3; ++i) {
		f[i] = bit.query(lower_bound(b + 1, b + 1 + *b, a[i] * 2 + 1) - b);
		bit.update(lower_bound(b + 1, b + 1 + *b, a[i]) - b, i);
	}
	rmq.init(n * 3, f);
	for (int i = 1; i <= n; ++i) {
		int l = i, r = n * 3, ans = -1;
		while (r - l >= 0) {
			int mid = (l + r) >> 1;
			if (rmq.queryMax(i, mid) >= i) {
				ans = mid;
				r = mid - 1;
			} else {
				l = mid + 1;
			}
		}
		if (ans == -1) res[i] = -1;
		else res[i] = ans - i;
	}
	for (int i = 1; i <= n; ++i)
		cout << res[i] << " \n"[i == n];
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr); cout.tie(nullptr);
	cout << fixed << setprecision(20);
	while (cin >> n) run();
	return 0;
}
posted @ 2019-10-22 08:45  Dup4  阅读(268)  评论(0编辑  收藏  举报