Codeforces Round #738 (Div. 2)A~D1手速场

A. Mocha and Math

题意:多组输入,任意次操作,每次操作选取一个区间[l,r],将\(a_{l+i}\)替换成\(a_{l+i}\)&\(a_{r-i}\),i是在这个区间的位置,从0开始,操作任意次,问最大值的最小值

分析:显然,在操作任意次的前提下,可以将一个数与任意数相与,所有数都可以达到理论最小值,所以答案就是n个数相与的结果

代码:

#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>

#define x first
#define y second

using namespace std;

typedef long long ll; 
typedef pair<int, int> PII;

const int N = 1e5 + 10, mod = 1e9 + 7;

int n, m, t, k;

int s[N], g[N], dp[N];

void solve()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> s[i];
	for (int i = 2; i <= n; i++)
		s[i] = s[i] & s[i-1];
	cout << s[n] << endl; 
}

int main()
{
    t = 1;
    cin >> t;
    while(t--) 
        solve();
    return 0;
}

B. Mocha and Red and Blue

题意:给定一个仅包含B?R的字符串,问号可替换B或R,对于一个字符串,它的代价为相邻元素相同个数最小,要求输出代价最小的字符串

分析:很显然的一个道理,在前面有确定的值的时候,与前面的不一样,绝对不会更差,所以首先将第一个赋值,后面跟着变就好了,有值不变,没值就变与前面不一样的,第一个如果是问号的话,找到第一个不是问号的位置,如果不存在,那第一个的值显然无所谓,哪个都可以,如果存在可以想出他的位置前面绝对是相间排列的,所以可以根据奇偶性算出第一个位置是什么元素。

代码:

#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>

#define x first
#define y second

using namespace std;

typedef long long ll; 
typedef pair<int, int> PII;

const int N = 1e5 + 10, mod = 1e9 + 7;

int n, m, t, k;

int s[N], g[N], dp[N];

char a[N];

void solve()
{
	cin >> n;
	cin >> a;
	int cnt = -1;
	for (int i = n - 1; i >= 0; i--)
		if (a[i] != '?')
			cnt = i;
	if (cnt == -1)
	{
		for (int i = 0; i < n; i++)
			if (i & 1)
				printf("B");
			else printf("R"); 
		puts("");
		return;
	}
	if (cnt % 2 == 0)
		a[0] = a[cnt];
	else if (a[cnt] == 'B')
		a[0] = 'R';
	else a[0] = 'B';
	for (int i = 0; i < n; i++)
	{
		if (a[i] == '?')
		{
			if (a[i-1] == 'B') 
				a[i] = 'R';
			else a[i] = 'B';
		}
		printf("%c", a[i]);
	}puts("");
}

int main()
{
    t = 1;
    cin >> t;
    while(t--) 
        solve();
    return 0;
}

C. Mocha and Hiking

题意:有n+1个村子,有2n-1条道路,对于位置为i的村庄,他们都有唯一的到达i+1的村庄的单向路,i属于1到n-1,还有n条单向路连接第i个村庄和第n+1个村庄,给出n个数,为0代表可以从该村庄可以直接到n+1,为1代表可以从n+1到该村庄。输出n个经过所有村庄且不重复的路线

分析:如果第n个村庄可以直接到达第n+1个村庄,那么直接输出1到n+1,如果第n+1个村庄可以直接到达第1个村庄,那么输出n+1,在输出1到n,否则一定存在相邻的村庄先到n+1,后从n+1到下一个村庄,因为01的连续性

代码:

#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>

#define x first
#define y second

using namespace std;

typedef long long ll; 
typedef pair<int, int> PII;

const int N = 1e5 + 10, mod = 1e9 + 7;

int n, m, t, k;

int s[N], g[N], dp[N];

void solve()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> s[i];
	if (s[n] == 0)
	{
		printf("1");
		for (int i = 2; i <= n + 1; i++)
			printf(" %d", i);
		puts("");
		return;
	}
	if (s[1] == 1)
	{
		printf("%d", n + 1);
		for (int i = 1; i <= n; i++)
			printf(" %d", i);
		puts("");
		return;
	}
	printf("1");
	for (int i = 2, j = 0; i <= n; i++)
	{
		if (j == 0 && s[i] == 1 && s[i-1] == 0) j = 1, printf(" %d", n + 1);
		printf(" %d", i);
	}
	puts("");
	return;
}

int main()
{
    t = 1;
    cin >> t;
    while(t--) 
        solve();
    return 0;
}

D1. Mocha and Diana (Easy Version)

题意:给出两个图,都有n个点,一个有m1条边,一个有m2条边,问最多可以连多少条边使得连接后两个图依旧是森林(没有环),输出数量,以此输出连哪几条边

分析:D1的范围是1000,n方暴力去找就好,贪心的想,能连就连就是最优的,而并查集能接近O(1)的复杂度判断两个点是否连通,暴力查找所有连接线,边连接边维护即可

代码:

#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>

#define x first
#define y second

using namespace std;

typedef long long ll; 
typedef pair<int, int> PII;

const int N = 1e5 + 10, mod = 1e9 + 7;

int n, m, t, k;

int s[N], g[N], dp[N], p[N], f[N];

vector<PII> vec;

int pfind(int u)
{
	return p[u] == u ? u : p[u] = pfind(p[u]);
}

int ffind(int u)
{
	return f[u] == u ? u : f[u] = ffind(f[u]);
}

void solve()
{
	int m1, m2;
	int a, b;
	cin >> n >> m1 >> m2;
	for (int i = 1; i <= n; i++)
		p[i] = f[i] = i;
	for (int i = 1; i <= m1; i++)
	{
		cin >> a >> b;
		p[pfind(a)] = pfind(b);
	}
	for (int i = 1; i <= m2; i++)
	{
		cin >> a >> b;
		f[ffind(a)] = ffind(b);
	}
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			if (pfind(i) != pfind(j) && ffind(i) != ffind(j))
			{
				p[pfind(i)] = pfind(j);
				f[ffind(i)] = ffind(j);
				vec.push_back({i, j});
			}
		}
	}
	cout << vec.size() << endl;
	for (int i = 0; i < vec.size(); i++)
		cout << vec[i].x << ' ' << vec[i].y << endl;
}

int main()
{
    t = 1;
//    cin >> t;
    while(t--) 
        solve();
    return 0;
}
posted @ 2021-08-16 10:37  forleaves  阅读(71)  评论(0)    收藏  举报