Codeforces Round #738 (Div. 2) A~D1题解
文章目录
A. Mocha and Math
-
题意
给你一个 n n n元素的数组。你可以进行任意次操作选定区间 [ l , r ] [l,r] [l,r],使得 a [ l ] = a [ l ] & a [ r ] , . . . . a [ r ] = [ r ] & a [ l ] a[l] = a[l]\& a[r],....a[r] = [r] \&a[l] a[l]=a[l]&a[r],....a[r]=[r]&a[l]。问使得所有情况中序列的最大值最小为多少? -
解题思路
由于可以进行任意次操作,而我们又得知 & \& &操作不会增大,所以我们必然可以让最大值变成所有数相 & \& &的值,这肯定是最小的,而这种操作刚好能符合我们这样做。故答案可得。 -
AC代码
/**
*@filename:A_Mocha_and_Math
*@author: pursuit
*@created: 2021-08-15 22:36
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 100 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int t,n,a[N];
int minn;
void solve(){
for(int i = 2; i <= n; ++ i){
a[1] = a[1] & a[i];
}
cout << a[1] << endl;
}
int main(){
scanf("%d", &t);
while(t -- ){
scanf("%d", &n);
for(int i = 1; i <= n; ++ i){
scanf("%d", &a[i]);
}
solve();
}
return 0;
}
B. Mocha and Red and Blue
-
题意
给你一个包含B,R,?的字符串,其中你需要将?替换成B,R,请你构造出使得连续B和连续R最小的字符串。 -
解题思路
贪心的去看这道题,我们即从已有的字符B,R出发,即如果存在一个字符是B,R,我们就可以贪心的构造其相邻的,只要让它们不连续则可局部最优,从而构成全局最优。 -
AC代码
/**
*@filename:B_Mocha_and_Red_and_Blue
*@author: pursuit
*@created: 2021-08-15 22:49
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int t,n;
string s;
void solve(){
char pre = 'a';
bool flag = false;
while(true){
bool flag1 = false,flag2 = false;
for(int i = 0; i < n; ++ i){
if(s[i] == 'B' || s[i] == 'R'){
flag1 = true;
if(i - 1 >= 0 && s[i - 1] == '?'){
if(s[i] == 'B')s[i - 1] = 'R';
else s[i - 1] = 'B';
flag2 = true;
}
if(i + 1 < n && s[i + 1] == '?'){
if(s[i] == 'R')s[i + 1] = 'B';
else s[i + 1] = 'R';
flag2 = true;
}
//cout << s[i] << " ";
}
}
if(!flag1){
s[0] = 'B';
}
if(flag1 && !flag2){
break;
}
}
cout << s << endl;
}
int main(){
cin >> t;
while(t -- ){
cin >> n >> s;
solve();
}
return 0;
}
C. Mocha and Hiking
-
题意
给你 n + 1 n+1 n+1个顶点的图,其中 1 1 1~ n n n中 i i i和 i + 1 i+1 i+1有一条边,能从 i i i到 i + 1 i+1 i+1。同时有一个数组 a a a,其中 a i = 0 a_i=0 ai=0则代表能从 i i i到 n + 1 n+1 n+1,若 a i = 1 a_i=1 ai=1则代表能从 n + 1 n+1 n+1到 i i i。问每个村庄只走一次,走完所有村庄的方案。 -
解题思路
对于 1 1 1~ n n n,由于我们只能从 i i i到 i + 1 i+1 i+1,所以我们的方案必然是从 i i i跳到 n + 1 n+1 n+1再从 n + 1 n+1 n+1回到 i i i,这样就必须满足 a i = 0 , a i + 1 = 1 a_i=0,a_{i+1}=1 ai=0,ai+1=1。特殊的情况即我们直接从 n + 1 n+1 n+1出发,或者最后到达 n + 1 n+1 n+1,这需要满足 a [ n ] = 0 a[n]=0 a[n]=0或者 a [ 0 ] = 1 a[0]=1 a[0]=1,这样才可满足构造条件。 -
AC代码
/**
*@filename:C_Mocha_and_Hiking
*@author: pursuit
*@created: 2021-08-15 23:25
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int t,n,a[N];
void solve(){
if(a[n] == 0){
for(int i = 1; i <= n + 1; ++ i){
printf("%d ", i);
}
puts("");
}
else if(a[1] == 1){
printf("%d ", n + 1);
for(int i = 1; i <= n; ++ i){
printf("%d ", i);
}
puts("");
}
else{
int idx = -1;
for(int i = 1; i < n; ++ i){
if(a[i] == 0 && a[i + 1] == 1){
idx = i;
break;
}
}
if(idx == -1){
puts("-1");
}
else{
for(int i = 1; i <= n; ++ i){
printf("%d ", i);
if(idx == i){
printf("%d ", n + 1);
}
}
}
}
}
int main(){
scanf("%d", &t);
while(t -- ){
scanf("%d", &n);
for(int i = 1; i <= n; ++ i){
scanf("%d", &a[i]);
}
solve();
}
return 0;
}
D1. Mocha and Diana (Easy Version)
-
题意
给你两棵森林,可以为它们添加相同的边,需要使得它们还是森林能添加的最大边数。 -
解题思路
树即是森林,说明白了这道题其实就是并查集裸题,我们只需要不出现环即可。所以我们利用两个并查集维护这两颗森林,先处理边,对于 D 1 D1 D1我们暴力处理所有边然后判断是否可以添加即可。 -
AC代码
/**
*@filename:D1_Mocha_and_Diana_Easy_Version_
*@author: pursuit
*@created: 2021-08-15 23:44
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;
int n,m[2],father[2][N];
int find(int op,int x){
return father[op][x] ^ x ? father[op][x] = find(op,father[op][x]) : x;
}
void solve(){
int res = 0;
vector<pii> ans;
int x,y,z,w;
for(int i = 1; i <= n; ++ i){
for(int j = 1; j <= n; ++ j){
x = find(0,i),y = find(0,j),z = find(1,i),w = find(1,j);
if((x ^ y) && (z ^ w)){
father[0][x] = y;
father[1][z] = w;
res ++;
ans.push_back({i,j});
}
}
}
printf("%d\n", res);
for(int i = 0; i < res; ++ i){
printf("%d %d\n", ans[i].first, ans[i].second);
}
}
int main(){
scanf("%d%d%d", &n, &m[0], &m[1]);
for(int i = 1; i <= n; ++ i){
father[0][i] = father[1][i] = i;
}
int u,v,fu,fv;
for(int i = 1; i <= m[0]; ++ i){
scanf("%d%d", &u, &v);
fu = find(0,u),fv = find(0,v);
if(fu ^ fv){
father[0][fu] = father[0][fv];
}
}
for(int i = 1; i <= m[1]; ++ i){
scanf("%d%d", &u, &v);
fu = find(1,u),fv = find(1,v);
if(fu ^ fv){
father[1][fu] = father[1][fv];
}
}
solve();
return 0;
}

浙公网安备 33010602011771号