Codeforces Round #622 (Div. 2) 题解和我的分析
Posted hebut-amadeus
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #622 (Div. 2) 题解和我的分析相关的知识,希望对你有一定的参考价值。
首先下午场非常适合中国人,开心
A
三种食物有个数限制,上菜,每次上菜跟以前的样式不能一样(食物的种类及个数各不相同),且每种食物最多用一次,问最多能上几次
对a,b,c排序,然后枚举上菜种类就可以了,注意最多能上7盘菜
#include<bits/stdc++.h> #define LL long long #define maxn 100010 using namespace std; int d[7][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}, {1, 1, 0}, {1, 0, 1}, {0, 1, 1}, {1, 1, 1}}; int main(){ int T; cin >> T; while(T--){ int a, b, c; cin >> a >> b >> c; if(a < b){ swap(a, b); } if(a < c){ swap(a, c); } if(b < c){ swap(b, c); } int ans = 0; for(int i = 0; i < 7; ++i){ if(a >= d[i][0] && b >= d[i][1] && c >= d[i][2]){ ans++; a = a - d[i][0]; b = b - d[i][1]; c = c - d[i][2]; } } cout << ans << endl; } return 0; }
B
就是有两场比赛,每场每个人都有一个独特的得分(从1到n),问给定分数最高排名跟最低排名(如果并列就按下算)
没有太多好说的,分析下可以知道第一个数是a+b-n+1,第二个数是a+b-1,注意让他们在1-n之间即可
#include<bits/stdc++.h> #define LL long long #define maxn 100010 using namespace std; int main(){ int T; cin >> T; while(T--){ int n, a, b; cin >> n >> a >> b; if(a + b < n){ cout << 1 << " " << min(a + b - 1, n) << endl; } else{ cout << min(a + b - n + 1, n) << " " << min(a + b - 1, n) << endl; } } return 0; }
C1 and C2
这个题的简单版本可以很轻松的暴力,这里主要说说C2的单调栈做法
首先这个a在建完之后一定有个峰值,在他的两边依次下降,那么我们怎么快速统计呢?可以用单调栈来做这个题
首先从1到n,如果栈不空且栈中元素大于当前元素,那么出栈一个数,否则结束,接下来我们统计如果这个点是峰值,左面的最大值
记录栈顶元素,如果栈空,则说明先前元素必须都得是当前元素,否则左边的最大值应该是从当前元素到栈顶元素全变为当前元素的总和加上栈顶元素做峰值的最大值
从1到n进行完一遍后,再从n到1进行一遍就易统计出右面的最大值
然后每个元素做峰值,序列总和最大值应该是左边+右面-当前元素的值,找到峰值之后,这个题便迎刃而解了
#include<bits/stdc++.h> #define LL long long #define maxn 500010 using namespace std; stack<int> st; LL use1[maxn], use2[maxn], a[maxn]; LL cl[maxn], rl[maxn]; signed main(){ int n; cin >> n; for(int i = 1; i <= n; ++i){ cin >> a[i]; } memset(use1, 0, sizeof use1); memset(use2, 0, sizeof use2); for(int i = 1; i <= n; ++i){ if(st.empty() || a[st.top()] <= a[i]){ use1[i] = a[i] + use1[i - 1]; st.push(i); } else{ while(!st.empty() && a[st.top()] > a[i]){ st.pop(); } if(st.empty()){ use1[i] = a[i] * i; } else{ use1[i] = a[i] * (i - st.top()) + use1[st.top()]; } st.push(i); } } while(!st.empty()){ st.pop(); } for(int i = n; i > 0; --i){ if(st.empty() || a[st.top()] <= a[i]){ use2[i] = a[i] + use2[i + 1]; st.push(i); } else{ while(!st.empty() && a[st.top()] > a[i]){ st.pop(); } if(st.empty()){ use2[i] = a[i] * (n - i + 1); } else{ use2[i] = a[i] * (st.top() - i) + use2[st.top()]; } st.push(i); } } LL ans = 0; int id = -1; for(int i = 1; i <= n; ++i){ //cout << use1[i] << " " << use2[i] << endl; if(use1[i] + use2[i] - a[i] > ans){ ans = use1[i] + use2[i] - a[i]; id = i; } } //cout << id << endl; for(int i = id; i <= n; ++i){ if(a[i] < a[i + 1]){ a[i + 1] = a[i]; } } for(int i = id; i > 0; --i){ if(a[i] < a[i - 1]){ a[i - 1] = a[i]; } } for(int i = 1; i <= n; ++i){ cout << a[i] << " "; } cout << endl; return 0; }
D跟E过的人不超过三位数,就不在考虑范围内了,这场难度偏难,虽然我也没想到打成这个b样子分还能涨一点
以上是关于Codeforces Round #622 (Div. 2) 题解和我的分析的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #622 (Div. 2)C(单调栈,DP)
Codeforces Round #622 (Div. 2)C2
CodeForces 622D Optimal Number Permutation
Codeforces Round #622 (Div. 2) C2. Skyscrapers (hard version)(单调栈,递推)
Codeforces Round #622 (Div. 2) 题解和我的分析
Codeforces Round #622 (Div. 2) C2. Skyscrapers (hard version) 单调栈