Codeforces Round #648 (Div. 2)
今天推结论的题偏多
A
一个n*m的棋盘有初始状态,俩人下棋,每次选一个点,这一行跟这一列都没棋子,然后往这个点放入棋子
问对着下,谁能先下不动
找全0行数跟全0列数的最小值即可,根据奇偶判断
#include<bits/stdc++.h>
#define LL long long
#define maxn 100010
using namespace std;
int mat[1010][1010];
int main(){
int T;
cin >> T;
while(T--){
int n, m;
cin >> n >> m;
for(int i = 0; i < n; ++i){
for(int j = 0; j < m; ++j){
cin >> mat[i][j];
}
}
int cnt1 = 0, cnt2 = 0;
for(int i = 0; i < n; ++i){
bool is1 = true;
for(int j = 0; j < m; ++j){
if(mat[i][j]){
is1 = false;
}
}
if(is1){
cnt1 = cnt1 + 1;
}
}
for(int i = 0; i < m; ++i){
bool is2 = true;
for(int j = 0; j < n; ++j){
if(mat[j][i]){
is2 = false;
}
}
if(is2){
cnt2 = cnt2 + 1;
}
}
if(min(cnt1, cnt2) % 2 == 0){
cout << "Vivek" << endl;
}
else{
cout << "Ashish" << endl;
}
}
return 0;
}
B
有n个元素,每个元素包含俩属性a跟b,当b不同时,俩元素可以交换位置,问能否让n个元素的a不递减排列
两个元素b相同时,也可以借助一个b不同的元素进行位置交换,所以只要有b不同的元素,就一定能转化为不递减排列
仅当所有元素b全部相同且排列不是非递减,才不能转化为不递减排列
#include<bits/stdc++.h> #define LL long long #define maxn 100010 using namespace std; int a[maxn]; int main(){ ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); int T; cin >> T; while(T--){ int n; cin >> n; bool add = true; for(int i = 0; i < n; ++i){ cin >> a[i]; if(i > 0 && a[i] < a[i - 1]){ add = false; } } int t, sum = 0; for(int i = 0; i < n; ++i){ cin >> t; sum = sum + t; } if((sum == 0 || sum == n) && !add){ cout << "No" << endl; } else{ cout << "Yes" << endl; } } return 0; }
C
有两个排列a跟b,问能否让b排列左移或右移一定位置,让a跟b排列重合的尽可能多
我们用map记录a排列每个元素向左移多少个才能到b对应的那个元素,另一个map记录向右移多少个
然后求这两个map中,最大的second值即可
#include<bits/stdc++.h> #define LL long long #define maxn 200010 using namespace std; int a[maxn], b[maxn], c[maxn], d[maxn]; map<int, int> mp1, mp2; int main(){ ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); int T; //cin >> T; T = 1; while(T--){ int n; cin >> n; for(int i = 0; i < n; ++i){ cin >> a[i]; c[a[i]] = i; } int ans = 0; for(int i = 0; i < n; ++i){ cin >> b[i]; int diff = (i - c[b[i]] + n) % n; if(mp1.find(diff) == mp1.end()){ mp1[diff] = 1; } else{ mp1[diff] = mp1[diff] + 1; } ans = max(ans, mp1[diff]); if(mp2.find(n - diff) == mp2.end()){ mp2[n - diff] = 1; } else{ mp2[n - diff] = mp2[n - diff] + 1; } ans = max(ans, mp2[n - diff]); } cout << ans << endl; } return 0; }
D
给一个n*m的地图,里面除了墙跟通路,还有B格(坏人)跟G格(好人),问你能否加一些墙,让所有坏人到不了出口((n,m)点),所有好人到的了出口
结论很简单,我们给坏人的上下左右,只要这一点不是坏人的位置都放上墙,然后判断出口能否dfs到所有好人
原因是如果每一个好人会被这样的墙堵上,说明坏人也可以从这条路走到终点,所以这样是正确的加墙方式
#include<bits/stdc++.h> #define LL long long #define maxn 55 using namespace std; char a[maxn][maxn]; bool vis[maxn][maxn]; int n, m; int _dfs(int x, int y){ if(x < 0 || x >= n || y < 0 || y >= m){ return 0; } if(vis[x][y] || a[x][y] == '#'){ return 0; } vis[x][y] = 1; int ret = 0; if(a[x][y] == 'G'){ ret = ret + 1; } ret = ret + _dfs(x + 1, y); ret = ret + _dfs(x - 1, y); ret = ret + _dfs(x, y + 1); ret = ret + _dfs(x, y - 1); return ret; } int main(){ ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); int T; cin >> T; while(T--){ cin >> n >> m; int sum = 0; for(int i = 0; i < n; ++i){ for(int j = 0; j < m; ++j){ cin >> a[i][j]; if(a[i][j] == 'G'){ sum = sum + 1; } } } for(int i = 0; i < n; ++i){ for(int j = 0; j < m; ++j){ if(a[i][j] == 'B'){ if(i != 0){ if(a[i - 1][j] != 'B'){ a[i - 1][j] = '#'; } } if(i != n - 1){ if(a[i + 1][j] != 'B'){ a[i + 1][j] = '#'; } } if(j != 0){ if(a[i][j - 1] != 'B'){ a[i][j - 1] = '#'; } } if(j != m - 1){ if(a[i][j + 1] != 'B'){ a[i][j + 1] = '#'; } } } } } memset(vis, 0, sizeof vis); if(sum == _dfs(n - 1, m - 1)){ cout << "Yes" << endl; } else{ cout << "No" << endl; } } return 0; }
E
有n个元素,让你从其中选出k个,对于每一个二进制位,如果这一位有max(k-2,1)个元素这一位是1,那么答案这一位是1,让你确定k跟这k个元素,输出最大值
结论是选3个元素最优,如果选2个元素,那么选第三个元素的答案一定大于等于选两个元素的答案,因为max(k-2,1)都是1,如果选4个元素,那么只有在选3个元素答案等于选的第4个元素时,才能让答案不减少,不然答案一定会减少(在之前选的3个元素是最优的情况下)
所以我们选最多3个元素,找他们并的最大值即可
#include<bits/stdc++.h> #define LL long long #define maxn 505 using namespace std; LL a[maxn]; int main(){ ios::sync_with_stdio(0); cin.tie(0), cout.tie(0); int n; cin >> n; for(int i = 0; i < n; ++i){ cin >> a[i]; } LL ans = 0; if(n <= 3){ for(int i = 0; i < n; ++i){ ans = ans | a[i]; } cout << ans << endl; return 0; } for(int i = 0; i < n; ++i){ for(int j = i + 1; j < n; ++j){ for(int k = j + 1; k < n; ++k){ ans = max(ans, a[i] | a[j] | a[k]); } } } cout << ans << endl; return 0; }
F题看起来也是能做的题,但是我昨天晚上做完E就去睡了
经典结论场,全是考验思维的题

浙公网安备 33010602011771号