Codeforces Round 874 (Div. 3)A-F

A. Musical Puzzle

思路:判断一下每每两个连接在一起的字符组成的字符串种类数

代码


#include
#include
#include
using namespace std;
int main()
{
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int t;
	cin >> t;
	while (t--)
	{
		int n;
		cin >> n;
		string str;
		cin >> str;
		map mp;
		int ans = 0;
		for (int i = 0; i < str.size() - 1; ++i)
		{
			string tmp;
			tmp += str[i], tmp += str[i + 1];
			if (mp.count(tmp) == 0) ++ans;
			mp[tmp] = 1;
		}
		cout << ans << '\n';
		mp.clear();
	}
	return 0;
}

B.Restore the Weather

思路:用pair arr数组来维护a数组,arr的first储存a数组当前位置下标,second储存a数组的值,用brr来维护b数组的值,然后将arr和brr数组根据值从小到大排序。再将每一个brr[i]的值填入对应的arr[i]的second中.

#include
#include
#include
#include
#include
using namespace std;
const int MAXN = 2e5;
pair arr[MAXN], crr[MAXN];
int brr[MAXN];
bool cmp(pair p1, pairp2)
{
	return p1.second < p2.second;
}
int main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int t;
	cin >> t;
	while (t--)
	{
		int n, k;
		cin >> n >> k;
		for (int i = 1; i <= n; ++i) cin >> arr[i].second, arr[i].first = i;
		for (int i = 1; i <= n; ++i) cin >> brr[i];
		sort(arr + 1, arr + 1 + n, cmp);
		sort(brr + 1, brr + 1 + n);
		for (int i = 1; i <= n; ++i) arr[i].second = brr[i];
		sort(arr + 1, arr + 1 + n);
		for (int i = 1; i <= n; ++i) cout << arr[i].second << " ";
		cout << '\n';
	}
	return 0;
}

C. Vlad Building Beautiful Array

思路:如果数组全是偶数或奇数,输出“YES”,否则找到数组中最小的数,判断是否的奇数,如果是奇数,则通过这个数,能让数组所有数变成奇数,这是输出YES.

#include
#include
#include
#include
#include
using namespace std;
const int MAXN = 2e5 + 5;
int arr[MAXN];
int main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int t;
	cin >> t;
	while (t--)
	{
		int n;
		cin >> n;
		int MIN = 1e9;
		int a = 0, b = 0;
		for (int i = 1; i <= n; ++i)
		{
			cin >> arr[i];
			if (arr[i] % 2 == 0) ++a;
			else ++b;
			MIN = min(arr[i], MIN);
		}
		if (a == 0 || b == 0) cout << "YES\n";
		else
		{
			if (MIN % 2 == 0) cout << "NO\n";
			else cout << "YES\n";
		}
	}
	return 0;
}

D. Flipper

思路:太麻烦了,不想说

#include
#include
#include
#include
#include
using namespace std;
const int MAXN = 2e5 + 5;
int arr[MAXN];
int main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int t;
	cin >> t;
	while (t--)
	{
		int n;
		cin >> n;
		int MAX = -1, l = 1, r = 0;
		if (n == 1)
		{
			int num;
			cin >> num;
			cout << num << '\n';
			continue;
		}
		if (n == 2)
		{
			int a, b;
			cin >> a >> b;
			cout << b << " " << a << '\n';
			continue;
		}
		for (int i = 1; i <= n; ++i)
		{
			cin >> arr[i];
			if (i >= 2 && MAX < arr[i]) MAX = arr[i], r = i;
		}
		deque d;
		for (int i = r; i <= n; ++i) d.push_back(arr[i]);
		if (arr[l] > arr[r - 1] && r == n)
		{
			for (int i = l; i < r; ++i) d.push_back(arr[i]);
			for (int i = 1; i < l; ++i) d.push_back(arr[i]);
		}
		else
		{
			d.push_back(arr[r - 1]);
			int rxp = r - 2;
			while (l <= rxp)
			{
				if (arr[l] > arr[rxp]) break;
				rxp--;
			}
			for (int i = r - 2; i > rxp; --i) d.push_back(arr[i]);
			for (int i = 1; i <= rxp; ++i) d.push_back(arr[i]);
		}
		for (int i = 0; i < d.size(); ++i) cout << d[i] << " ";
		cout << '\n';
	}
	return 0;
}

E. Round Dance

思路:这个数组里面所有数值连在一起不是环就是链,如果找最大值就是判断环和链的个数,这个可以用并查集,如果是找最小值的话,就是找最大的环,但是数组中的这些小环是不可能拆开组成最大环的,而链可以一起组成最大环,所以找完最大环后,还有把这些小环的个数加上。找环有个技巧,也不算是吧,如果一个数组的子序列的下标组成的一个数组是它们的fa[]组成的一个数组的一个排列,则这个子序列构成一个环,即

fa    1 2 3

idex 3 2 1

PS:下面arr是上面的fa,而下面的fa是第i个数的祖宗,两个数构成的环按照题目要求,是不算环的,算链的

#include
#include
#include
#include
#include
using namespace std;
const int MAXN = 2e5 + 5;
int arr[MAXN], fa[MAXN], vis[MAXN];
priority_queue, greater> que[MAXN];
int find(int x)
{
	if (fa[x] == x) return x;
	else return fa[x] = find(fa[x]);
}
int main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int t;
	cin >> t;
	while (t--)
	{
		int n;
		cin >> n;
		for (int i = 1; i <= n; ++i)
		{
			fa[i] = i, vis[i] = 0;
			cin >> arr[i];
		}
		int MAX = 0, MIN = 0;
		for (int i = 1; i <= n; ++i)
		{
			int fi = find(arr[i]);
			fa[find(i)] = fi;
		}
		for (int i = 1; i <= n; ++i)
		{
			int fi = find(i);
			que[fi].push(arr[i]), que[fi].push(i);
			if (!vis[fi]) ++MAX;
			++vis[fi];  
		}
		int cnt = 0;
		for (int i = 1; i <= n; ++i)
		{
			int flag = 0;
			if (vis[i] > 2)
			{
				int a = 0, b = 0;
				if (que[i].empty()) continue;
				while (que[i].size())
				{
					a = que[i].top(), que[i].pop();
					b = que[i].top(), que[i].pop();
					if (a != b) flag = 1;
				}
				if (flag == 0)++MIN, cnt += vis[i];
			}
		}
		cout << max(MIN + (cnt != n), 1) << " " << MAX << '\n';
	}
	return 0;
}

F,Ira and Flamenco

用滑动窗口,窗口里的数是第i个时段满足条件二和三,但不满足条件一的集合,求条件一可以用C的方式,即从含有a个数的窗口中取b个数的方法。由于可能出现重复的数,这时候用val维护每一个数出现的个数,ret则代表窗口内重复的数的个数和的乘积

#include
#include
#include
#include
#include
using namespace std;
const int MAXN = 2e6 + 5;
#define int unsigned long long
#define LL unsigned long long
int arr[MAXN], f[MAXN];
unordered_map  val;
const int mod = 1e9 + 7;
LL qkpow(LL a, LL p, LL mod)
{
	LL t = 1, tt = a % mod;
	while (p)
	{
		if (p & 1)t = t * tt % mod;
		tt = tt * tt % mod;
		p >>= 1;
	}
	return t;
}
LL getInv(LL a, LL mod)
{
	return qkpow(a, mod - 2, mod);
}
int C(int n, int m)
{
	if (n < m) return 0;
	int a = f[n];
	int b = getInv(f[n - m], mod);
	int c = getInv(f[m], mod);
	return (((a * b) % mod) * c) % mod;
}
signed main()
{
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int t;
	cin >> t;
	deque d;
	f[0] = f[1] = 1;
	for (int i = 2; i < MAXN; ++i)
		f[i] = (f[i - 1] * i) % mod;
	while (t--)
	{
		int n, m;
		cin >> n >> m;
		for (int i = 1; i <= n; ++i) cin >> arr[i];
		sort(arr + 1, arr + 1 + n);
		for (int i = 1; i <= n; ++i) ++val[arr[i]];
		int ans = 0, ret = 1;
		for (int i = 1; i <= n; ++i)
		{
			while (d.size() && arr[i] - arr[d.front()] >= m)
			{
				if (d.size() >= m) ans = (ans + (ret * C(d.size(), m)) % mod) % mod;
				ret = (getInv(val[arr[d.front()]], mod) * ret) % mod;
				d.pop_front();
			}
			int flag = 0;
			if ((d.size() && arr[d.back()] != arr[i]) || d.empty()) d.push_back(i), ret = (ret * val[arr[i]]) % mod;
		}
		if (d.size()) ans = (ans + (ret * C(d.size(), m)) % mod) % mod;
		cout << ans << '\n';
		d.clear(), val.clear();
	}
	return 0;
}

你可能感兴趣的:(算法,c++,数据结构)