返回顶部

AtCoder Beginner Contest 245题解

赛时做到F

A - Good morning

题目描述:给你两个同一天内的24时的时间,判断那一个时间更早。

思路:根据题意模拟即可。

时间复杂度:\(O(1)\)

参考代码:

void solve() {
	int a, b, c, d;
	cin >> a >> b >> c >> d;
	string res = "Takahashi";
	if (c < a || (c == a && d < b)) res = "Aoki";
	cout << res << '\n';
	return;
}

B - Mex

题目描述:给你一个数组,找出其中的MEX

思路:根据题意模拟即可

时间复杂度:\(O(n)\)

参考代码:

void solve() {
	vector<int>cnt(2005, 0);
	int n, a;
	cin >> n;
	for (int i = 1; i <= n; ++i) {
		cin >> a;
		cnt[a]++;
	}
	int res = 0;
	while (cnt[res] != 0) ++res;
	cout << res << '\n';
	return;
}

C - Choose Elements

题目描述:给你两个长度为n的数组A , B和一个正整数 K,你每次可以从A_iB_i中选一个,然后按照顺序组成新数组C,问这样组成的新数组是否满足\(|C_i - C_{i + 1}| \leq K , \forall 1 \leq i < n\)

思路:比较明显,C的第一个只能是\(A_1\)或者\(B_1\),那么我们分别以他们开始进行检验,每次可以根据当前值将下一个数的值的范围确定下来,若下一个数满足范围就可以设定新的范围,然后模拟即可。

时间复杂度:\(O(n)\)

参考代码:

void solve() {
	int n, k;
	cin >> n >> k;
	vector<int>a(n + 1, 0), b(n + 1, 0);
	for (int i = 1; i <= n; ++i) cin >> a[i];
	for (int i = 1; i <= n; ++i) cin >> b[i];
	auto check = [&](int lr, int rs) {
		int lastlr = lr, lastrs = rs;
		for (int i = 1; i <= n; ++i) {
			if (a[i] >= lastlr && a[i] <= lastrs) {
				if (b[i] < lastlr || b[i] > lastrs) lr = a[i] - k, rs = a[i] + k;
				else lr = min(a[i] - k, b[i] - k), rs = max(a[i] + k, b[i] + k);
			}
			else if (b[i] >= lastlr && b[i] <= lastrs) lr = b[i] - k, rs = b[i] + k;
			else return false;
			lastlr = lr;
			lastrs = rs;
		}
		return true;
	};
	if (check(a[1], a[1]) || check(b[1], b[1])) cout << "Yes" << '\n';
	else cout << "No" << '\n';
	return;
}

D - Polynomial division

题目描述:存在两个长度分别为\(n + 1\)\(m + 1\)的多项式\(A,B\),他们的乘积为\(C\),现在已知\(A , C\),求\(B\)

思路:考虑到这题数据量很小,不需要使用加速优化,直接按照除法模拟即可。

时间复杂度:\(O(nm)\)

参考代码:

void solve() {
	int n, m;
	cin >> n >> m;
	vector<int>a(n + 1, 0),b(m + 1, 0), c(n + m + 1, 0);
	for (int i = 0; i <= n; ++i) cin >> a[i];
	for (int i = 0; i <= n + m; ++i) cin >> c[i];
	int len = n + m;
	for (int j = m; j >= 0; --j) {
		if (c[len] == 0) b[j] = 0;
		else b[j] = c[len] / a[n];
		for (int i = 0; i <= n; ++i) c[i + j] -= b[j] * a[i];
		--len;
	}
	for (auto&& num : b) cout << num << " ";
	return;
}

E - Wrapping Chocolate

题目描述:有\(n\)个长方形的巧克力,第\(i\)个巧克力的长宽分别是\(A_i\)\(B_i\),有\(m (n \leq m)\)个长方形盒子,第\(i\)个盒子的长宽分别为\(C_i\)\(D_i\)。当第\(j\)个盒子可以装下第\(i\)个巧克力时,必须满足条件\(A_i \leq C_j\)\(B_i \leq D_j\)。问是否可以将所有巧克力都装入盒子中。

思路:假定长宽分别用\(x\)\(y\)表示,那么我们按照\(y\)排序之后,倒序枚举贪心,对于当前枚举的巧克力,找最小的\(x\)满足\(x\)大于等于其长度即可。这个\(x\)可以用一个multiset维护。

时间复杂度:\(O(nlogn)\)

参考代码:

struct Node {
	int u, v;
	Node(int _u = 0 , int _v = 0):u(_u) , v(_v){}
};
void solve() {
	int n, m;
	cin >> n >> m;
	vector<Node>a(n + 1), b(m + 1);
	for (int i = 1; i <= n; ++i) cin >> a[i].u;
	for (int i = 1; i <= n; ++i) cin >> a[i].v;
	for (int i = 1; i <= m; ++i) cin >> b[i].u;
	for (int i = 1; i <= m; ++i) cin >> b[i].v;
	sort(a.begin(), a.end(), [&](const Node& a, const Node& b) {
		return a.v < b.v;
		});
	sort(b.begin(), b.end(), [&](const Node& a, const Node& b) {
		return a.v < b.v;
		});
	multiset<int> st;
	int idx = m;
	for (int i = n; i >= 1; --i) {
		while (idx > 0 && b[idx].v >= a[i].v) st.insert(b[idx].u), --idx;
		if (st.empty()) {
			cout << "No" << '\n';
			return;
		}
		auto iter = st.lower_bound(a[i].u);
		if (iter == st.end()) {
			cout << "No" << '\n';
			return;
		}
		st.erase(iter);
	}
	cout << "Yes" << '\n';
	return;
}

F - Endless Walk

题目描述:给你\(n\)个点\(m\)条边的有向图,问你有多少个顶点满足:从该点出发,可以无限走下去。

思路:明显有环的时候就可以无限走下去,若一个点可以到达这个环,说明它也可以无限走下去。所以我们可以使用tarjan算法缩点之后建反图,从连通分量大于1的新结点出发做BFS,最终统计点的数量即可。这个做法比较垃圾,被某位神嘲讽了QAQ。

时间复杂度:\(O(n + m)\)

参考代码:

void solve() {
	int n, m;
	cin >> n >> m;
	vector<vector<int>>graph(n + 1);
	for (int i = 1; i <= m; ++i) {
		int u, v;
		cin >> u >> v;
		graph[u].push_back(v);
	}
	vector<int>dfn(n + 1, 0), low(n + 1, 0);
	int dfncnt = 0;
	vector<int>s(n + 1, 0), inStack(n + 1, 0);
	int top = 0;
	vector<int>scc(n + 1, 0), sz(n + 1, 0);
	int sc = 0;
	auto tarjan = [&](auto&& tarjan, int u)->void {
		low[u] = dfn[u] = ++dfncnt;
		s[++top] = u;
		inStack[u] = 1;
		for (auto& v : graph[u]) {
			if (!dfn[v]) {
				tarjan(tarjan, v);
				low[u] = min(low[u], low[v]);
			}
			else if (inStack[v]) low[u] = min(low[u], dfn[v]);
		}
		if (dfn[u] != low[u]) return;
		++sc;
		while (s[top] != u) {
			scc[s[top]] = sc;
			sz[sc]++;
			inStack[s[top--]] = 0;
		}
		scc[s[top]] = sc;
		sz[sc]++;
		inStack[s[top--]] = 0;
		return;
	};
	for (int i = 1; i <= n; ++i) {
		if (dfn[i]) continue;
		tarjan(tarjan, i);
	}
	map<int, int>mp;
	for (int i = 1; i <= n; ++i) mp[scc[i]]++;
	vector<vector<int>>ngraph(sc + 1);
	for (int i = 1; i <= n; ++i) {
		for (auto&& v : graph[i]) {
			ngraph[scc[v]].push_back(scc[i]);
		}
	}
	queue<int>q;
	vector<bool>vis(sc + 1, 0);
	for (int i = 1; i <= sc; ++i) {
		if (mp[i] > 1) q.push(i), vis[i] = true;
	}
	while (!q.empty()) {
		auto u = q.front(); q.pop();
		for (auto& v : ngraph[u]) {
			if (vis[v]) continue;
			vis[v] = true;
			q.push(v);
		}
	}
	int res = 0;
	for (int i = 1; i <= sc; ++i)if (vis[i]) res += mp[i];
	cout << res << '\n';
	return;
}
posted @ 2022-03-27 10:22  cherish-lgb  阅读(140)  评论(1编辑  收藏  举报