Codeforces Round #622 (Div. 2)解题报告

Codeforces Round #622 (Div. 2)

【A.Fast Food Restaurant】

【题目大意】
有ABC3种饺子,个数分别为a,b,c,现在问你这些饺子最多可以给多少个人享用,且满足
1.每个客人享用的的每种饺子数目不超过1
2.每个客人享用的饺子必须不同
3.每个客人至少要享用一个饺子

【解题思路】
可以将所有情况列举出来,客人享用的饺子种类可能为:
A,B,C,AB,AC,BC,ABC
一共只有7种,也就是说答案最大是7
考虑贪心,肯定先考虑一种,再考虑两种,最后考虑三种的情况,能分就分

【AC代码】

#include 
using namespace std;
#define endl '\n'
void Swap(int& a, int& b, int& c) {
	if (a < b) swap(a, b);
	if (a < c) swap(a, c);
	if (b < c) swap(b, c);
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	int T;
	cin >> T;
	while (T--) {
		int a, b, c;
		cin >> a >> b >> c;
		Swap(a, b, c);
		int ans = 0;
		if (a) { ++ans; --a; }
		if (b) { ++ans; --b; }
		if (c) { ++ans; --c; }
		if (a && b) { ++ans; --a, --b; }
		if (a && c) { ++ans; --a, --c; }
		if (b && c) { ++ans; --b, --c; }
		if (a && b && c) { ++ans; --a, --b, --c; }
		cout << ans << endl;
	}
	return 0;
}

【B.Different Rules】

【题目大意】
有n个人进行比赛,比赛分为两轮,给定一个人两轮的排名x和y,问最后他的排名的最大值和最小值是多少

【解题思路】
MD这是个结论题,我TM结果都推出来了,但是忘了答案要与n取最小

具体证明可以看正解

【AC代码】

#include 
using namespace std;
#define endl '\n'
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	int T;
	cin >> T;
	while (T--) {
		int n, x, y;
		cin >> n >> x >> y;
		if (x < y) swap(x, y);
		int sum = x + y;
		cout << min(max(sum - n + 1, 1), n) << " " << min(sum - 1, n) << endl;
	}
	return 0;
}

【C1.Skyscrapers (easy version)】

【题目大意】
有n快空地,每块空地可以建造高度ai不超过mi的楼层,且不能存在j < i < k and aj > ai < ak,问楼层总数最大的情况

【解题思路】
很容易想到楼层的高度应该满足先增后减的情况,那么我们枚举ai作为最高点的情况找到最大值即可,由于n < 1000,所以O(n2)不会超时

【AC代码】

#include 
using namespace std;
#define endl '\n'
typedef long long ll;
ll a[1010];
ll b[1010];
ll c[1010];
ll n, Max;
inline void solve(register int index) {
	for (register int i = 1; i <= n; ++i) {
		b[i] = a[i];
	}
	register ll sum = b[index];
	for (register int i = index - 1; i >= 1; --i) {
		if (b[i] > b[i + 1]) b[i] = b[i + 1];
		sum += b[i];
	}
	for (register int i = index + 1; i <= n; ++i) {
		if (b[i] > b[i - 1]) b[i] = b[i - 1];
		sum += b[i];
	}
	if (sum > Max) {
		for (register int i = 1; i <= n; ++i) c[i] = b[i];
		Max = sum;
	}
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	cin >> n;
	for (register int i = 1; i <= n; ++i) {
		cin >> a[i];
	}
	for (register int i = 1; i <= n; ++i) solve(i);
	for (register int i = 1; i <= n; ++i) cout << c[i] << " ";
	cout << endl;
	return 0;
}

【C2.Skyscrapers (hard version)】

【题目大意】
和上一题一样,但是n变成了500000

【解题思路】
n变成了500000,那么暴力肯定超时,我们考虑用单调栈来记录距离ai最左和最右的最小值的下标,然后开两个数组分别记录a1 - ai、ai - an的楼层的高度和,那么最高点就是两个数组的和减去mi最大的位置,然后以这个位置为最高点修改ai即可

【AC代码】

#include 
using namespace std;
#define endl '\n'
typedef long long ll;
ll a[500010];
ll b[500010];
ll c[500010];
ll sta[500010];
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; ++i) cin >> a[i];
	int top = 0;
	for (int i = 1; i <= n; ++i) {
		while (top > 0 && a[sta[top]] > a[i]) --top;
		b[i] = b[sta[top]] + (i - sta[top]) * a[i];
		sta[++top] = i;
	}
	top = 0;
	sta[0] = n + 1;
	for (int i = n; i >= 1; --i) {
		while (top > 0 && a[sta[top]] > a[i]) --top;
		c[i] = c[sta[top]] + (sta[top] - i) * a[i];
		sta[++top] = i;
	}
	ll Max = 0;
	int index = 0;
	for (int i = 1; i <= n; ++i) {
		if (Max < b[i] + c[i] - a[i]) {
			Max = b[i] + c[i] - a[i];
			index = i;
		}
	}
	for (int i = index - 1; i >= 1; --i) {
		if (a[i] > a[i + 1]) a[i] = a[i + 1];
	}
	for (int i = index + 1; i <= n; ++i) {
		if (a[i] > a[i - 1]) a[i] = a[i - 1];
	}
	for (int i = 1; i <= n; ++i) cout << a[i] << " ";
	return 0;
}

你可能感兴趣的:(codeforces)