Codeforces Round #627 (Div. 3) - 题解与我的分析
这场时间也不错,虽然对于我是unrated,然而为了保持手感还是打了
A
给你一个俄罗斯方块的现状态,问你只用1*2(底是1,高是2)的方块能否让所有的方块消掉
很简单吧,如果a[i]跟a[j]相差是1,3,5...这样的奇数,那么怎么填也不行
如果所有的a[i]与a[j],a[i] - a[j]的绝对值对2取模是0,那么就是yes,否则是no
#include<bits/stdc++.h> #define LL long long #define maxn 100010 using namespace std; int a[maxn]; int main(){ int T; cin >> T; while(T--){ int n; bool good = true; cin >> n; for(int i = 0; i < n; ++i){ cin >> a[i]; for(int j = i - 1; j >= 0; --j){ if(abs(a[i] - a[j]) % 2 == 1){ good = false; } } } cout << (good ? "YES" : "NO") << endl; } return 0; }
B
对于一个数列来说,问你是否有长大于等于3的回文数列,例如[1,3,1]或者[1,2,2,1]这样的
结论异常的简单,无论对于长是奇数还是偶数的回文数列,一定有相隔超过1,数字相等的两个位置。
只要有这样的位置,那么就是yes,否则就是no
用map的线性算法或者暴力的平方复杂度都可以
#include<bits/stdc++.h> #define LL long long #define maxn 100010 using namespace std; int a[maxn]; int main(){ int T; cin >> T; while(T--){ int n; cin >> n; bool good = false; for(int i = 0; i < n; ++i){ cin >> a[i]; for(int j = i - 2; j >= 0; --j){ if(a[i] == a[j]){ good = true; } } } cout << (good ? "YES" : "NO") << endl; } return 0; }
C
青蛙在0位置要到n+1的位置,0到n+1之间有长为n的,只包含L或R的字符串,L说明可以往左跳,R说明可以向右跳,每次最多跳t的长度
问你保证能跳到n+1的位置上的情况下,t的最小值
分析下,如果你跳到L位置,最终还是会跳到更近的R位置,所以无论怎么样,我们跳到L位置上的长度>=我们不跳到L位置上的长度
那么我们只考虑跳到R位置上的长度,吧0跟n+1也想成R位置,算出相近的R,位置之差的最大值即可
#include<bits/stdc++.h> #define LL long long #define maxn 200010 using namespace std; int a[maxn]; int main(){ int T; cin >> T; while(T--){ string s; cin >> s; int n = s.size(); int now = -1, ans = 0; for(int i = 0; i < n; ++i){ if(s[i] == 'R'){ ans = max(i - now, ans); now = i; } } ans = max(n - now, ans); cout << ans << endl; } return 0; }
D
有n节课,每节课都有a[i]和b[i]属性,问你满足i>j,a[i]+a[j]>b[i]+b[j]的组有多少
a[i] - b[i] > -(a[j] - b[j]),我们存一下-(a[i] - b[i]),然后排序,每个i二分找比多少-(a[i] - b[i])大即可
注意如果a[i]-b[i]>0的话,会把本身也算进去一遍,这个时候减去1就行了
#include<bits/stdc++.h> #define LL long long #define maxn 200010 using namespace std; int a[maxn], b[maxn], c[maxn]; int main(){ int n; cin >> n; for(int i = 0; i < n; ++i){ cin >> a[i]; } for(int i = 0; i < n; ++i){ cin >> b[i]; } for(int i = 0; i < n; ++i){ c[i] = b[i] - a[i]; } LL ans = 0; sort(c, c + n); for(int i = 0; i < n; ++i){ int now = lower_bound(c, c + n, a[i] - b[i]) - c; if(a[i] - b[i] > 0){ ans--; } ans = ans + now; } cout << ans / 2 << endl; return 0; }
E
一天有h小时,主人公要睡n次觉,一次可以睡a[i]小时或者a[i]-1个小时,醒了马上就要睡下一觉直到睡完n次,如果睡觉起来的时候时间(如果时间大于一天就要对h取模)在l到r之间,那么这一觉就是good,加一分,问你睡完这n次,最多得多少分
显然局部最优解无法推出全局最优解,我们考虑dp来储存状态
dp[i][j]表示睡完第i次时,有j次睡了a[i]-1个小时,i-j次睡了a[i]个小时的最大得分
转移方程就很好想了,从i-1天的j-1跟j状态转移即可
答案就是i从0-n,dp[n][i]的最大值
#include<bits/stdc++.h> #define LL long long #define maxn 2010 using namespace std; int dp[maxn][maxn]; int main(){ int n, h, l, r, t; LL sum = 0; cin >> n >> h >> l >> r; int ans = 0; for(int i = 1; i <= n; ++i){ cin >> t; sum = sum + t; for(int j = 0; j <= i; ++j){ int good = (l <= ((sum - j) % h) && ((sum - j) % h) <= r) ? 1 : 0; //cout << ((sum - j) % n) << " " << good << endl; if(j == 0){ dp[i][j] = dp[i - 1][j] + good; } else if(j == i){ dp[i][j] = dp[i - 1][j - 1] + good; } else{ dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1]) + good; } ans = max(ans, dp[i][j]); } } cout << ans << endl; return 0; }
F题👴偷个小懒,嘻嘻
整体来看这次还是比较简单的,偏向思维的题多一些

浙公网安备 33010602011771号