Educational Codeforces Round 76 (Rated for Div. 2)(A~F)

A - Two Rival Students

You are the gym teacher in the school.

There are nn students in the row. And there are two rivalling students among them. The first one is in position aa, the second in position bb. Positions are numbered from 11 to nn from left to right.

Since they are rivals, you want to maximize the distance between them. If students are in positions pp and ss respectively, then distance between them is |p−s||p−s|.

You can do the following operation at most xx times: choose two adjacent (neighbouring) students and swap them.

Calculate the maximum distance between two rivalling students after at most xx swaps.

题意:有长度为n的序列,有两个位置分别为a跟b的学生,他们有矛盾,现在你可以交换x次使得

他们之间的距离最大,交换的人必须是位置相邻的。

思路:直接模拟,能暴力就别想别的。

#include <iostream>
#include <algorithm>
#include <ctime>
#include <cstdio>
#include <bits/stdc++.h>
//#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
 
#ifdef LOCAL
#define debug(x) cout << "[" __FUNCTION__ ": " #x " = " << (x) << "]\n"
#define TIME cout << "RuningTime: " << clock() << "ms\n", 0
#else
#define TIME 0
#endif
#define hash_ 1000000009
#define Continue(x) { x; continue; }
#define Break(x) { x; break; }
ll fpow(ll a, int b, int mod) { ll res = 1; for (; b > 0; b >>= 1) { if (b & 1) res = res * a % mod; a = a * a % mod; } return res % mod; }
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
int main()
{
#ifdef LOCAL
	freopen("D:/input.txt", "r", stdin);
#endif
	int t;
	cin >> t;
	while (t--)
	{
		int n, x, a, b;
		cin >> n >> x >> a >> b;
		if (a > b)
			swap(a, b);
		while (x != 0)
		{
			if (b == n)
				break;
			x--;
			b++;
		}
		while (x != 0)
		{
			if (a == 1)
				break;
			x--;
			a--;
		}
		cout << b - a << endl;
	}
	return TIME;
}

B - Magic Stick

Recently Petya walked in the forest and found a magic stick.

扫描二维码关注公众号,回复: 11887503 查看本文章

Since Petya really likes numbers, the first thing he learned was spells for changing numbers. So far, he knows only two spells that can be applied to a positive integer:

  1. If the chosen number aa is even, then the spell will turn it into 3a23a2;
  2. If the chosen number aa is greater than one, then the spell will turn it into a−1a−1.

Note that if the number is even and greater than one, then Petya can choose which spell to apply.

Petya now has only one number xx. He wants to know if his favorite number yy can be obtained from xx using the spells he knows. The spells can be used any number of times in any order. It is not required to use spells, Petya can leave xx as it is.

题意:给出一个x,跟一个y,问x能不能通过题目中给的变化得到y,变化就是①偶数可以乘个二分之三。

②大于1了就可以减1;

思路:直接模拟,因为有2号操作,所以如果一旦x变化的值大于y就直接break。再用一个map记录,如果

变化过程中有重复的值出现意味着不能变化到直接break就可以了。

#include <iostream>
#include <algorithm>
#include <ctime>
#include <cstdio>
#include <bits/stdc++.h>
//#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
 
#ifdef LOCAL
#define debug(x) cout << "[" __FUNCTION__ ": " #x " = " << (x) << "]\n"
#define TIME cout << "RuningTime: " << clock() << "ms\n", 0
#else
#define TIME 0
#endif
#define hash_ 1000000009
#define Continue(x) { x; continue; }
#define Break(x) { x; break; }
ll fpow(ll a, int b, int mod) { ll res = 1; for (; b > 0; b >>= 1) { if (b & 1) res = res * a % mod; a = a * a % mod; } return res % mod; }
const int mod = 1e9 + 7;
const int N = 1e5 + 10;
map<ll, int>mp;
int main()
{
#ifdef LOCAL
	freopen("D:/input.txt", "r", stdin);
#endif
	int t;
	cin >> t;
	while (t--)
	{
		mp.clear();
		int flag = 0;
		ll x, y;
		cin >> x >> y;
		if (x == y)
			Continue(puts("YES"));
		while (true)
		{
			if (x % 2 == 0)
				x = x / 2 * 3;
			else
				x--, x = x / 2 * 3;
			if (x >= y)
				Break(flag = 1);
			if (mp[x])
				break;
			mp[x] = 1;
		}
		if (flag)
			puts("YES");
		else
			puts("NO");
	}
	return TIME;
}

C - Dominated Subarray

Let's call an array t dominated by value v in the next situation.

At first, array t should have at least 2 elements. Now, let's calculate number of occurrences of each number num in t and define it as occ(num). Then t is dominated (by v) if (and only if) occ(v)>occ(v′) for any other number v′. For example, arrays [1,2,3,4,5,2], [11,11] and [3,2,3,2,3] are dominated (by 2, 11 and 3 respectevitely) but arrays [3], [1,2] and [3,3,2,2,1] are not.

Small remark: since any array can be dominated only by one number, we can not specify this number and just say that array is either dominated or not.

You are given array a1,a2,…,an. Calculate its shortest dominated subarray or say that there are no such subarrays.

The subarray of a is a contiguous part of the array a, i. e. the array ai,ai+1,…,aj for some 1≤i≤j≤n.

题意:给出一个序列,要求找出他的长度最小的区间,满足区间内有唯一的众数。

思路:直接记录一下每个数出现的位置, 然后计算的过程中当前位置减去上一次这个数出现的位置取个min就可以了。

#include <iostream>
#include <algorithm>
#include <ctime>
#include <cstdio>
#include <bits/stdc++.h>
//#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
 
#ifdef LOCAL
#define debug(x) cout << "[" __FUNCTION__ ": " #x " = " << (x) << "]\n"
#define TIME cout << "RuningTime: " << clock() << "ms\n", 0
#else
#define TIME 0
#endif
#define hash_ 1000000009
#define Continue(x) { x; continue; }
#define Break(x) { x; break; }
ll fpow(ll a, int b, int mod) { ll res = 1; for (; b > 0; b >>= 1) { if (b & 1) res = res * a % mod; a = a * a % mod; } return res % mod; }
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
int a[N];
int vis[N];
int main()
{
#ifdef LOCAL
	freopen("D:/input.txt", "r", stdin);
#endif
	int t;
	cin >> t;
	while (t--)
	{
		int n;
		cin >> n;
		for (int i = 1; i <= n; i++)
			scanf("%d", &a[i]);
		int MX = 0x3f3f3f3f;
		for (int i = 1; i <= n; i++)
		{
			if (vis[a[i]] == 0)
				vis[a[i]] = i;
			else
			{
				MX = min(MX, i - vis[a[i]] + 1);
				vis[a[i]] = i;
			}
		}
		if (MX == 0x3f3f3f3f)
			cout << -1 << endl;
		else
			cout << MX << endl;
		for (int i = 1; i <= n; i++)
			vis[a[i]] = 0;
	}
	return TIME;
}

 D - Yet Another Monster Killing Problem

You play a computer game. In this game, you lead a party of mm heroes, and you have to clear a dungeon with nn monsters. Each monster is characterized by its power aiai. Each hero is characterized by his power pipi and endurance sisi.

The heroes clear the dungeon day by day. In the beginning of each day, you choose a hero (exactly one) who is going to enter the dungeon this day.

When the hero enters the dungeon, he is challenged by the first monster which was not defeated during the previous days (so, if the heroes have already defeated kk monsters, the hero fights with the monster k+1k+1). When the hero fights the monster, there are two possible outcomes:

  • if the monster's power is strictly greater than the hero's power, the hero retreats from the dungeon. The current day ends;
  • otherwise, the monster is defeated.

After defeating a monster, the hero either continues fighting with the next monster or leaves the dungeon. He leaves the dungeon either if he has already defeated the number of monsters equal to his endurance during this day (so, the ii-th hero cannot defeat more than sisi monsters during each day), or if all monsters are defeated — otherwise, he fights with the next monster. When the hero leaves the dungeon, the current day ends.

Your goal is to defeat the last monster. What is the minimum number of days that you need to achieve your goal? Each day you have to use exactly one hero; it is possible that some heroes don't fight the monsters at all. Each hero can be used arbitrary number of times.

题意:有n个怪兽,每个怪兽有个血量,再给出m个奥特曼,每个奥特曼两个属性攻击力跟耐久力

每天可以派一个奥特曼出战,能战胜怪兽的条件是其攻击力大于怪兽的血量,每消灭一个怪兽耐久力

就会减少一个,当耐久力为0或者怪兽被消灭完则退出战斗。

思路:这题可以O(n)的,定义个d数组表示能攻击i天的最大攻击力。然后每次枚举能攻击的天数j,如果

d[j]≥这j天的最大值则继续尝试增加天数,否则break。

这个d数组的求法就是求个后缀最值就可以了,因为考虑个问题,如果能攻击i天的最大攻击力为j,那么

j这个攻击力也一定能攻击i - 1天。

#include <iostream>
#include <algorithm>
#include <ctime>
#include <cstdio>
#include <bits/stdc++.h>
//#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
 
#ifdef LOCAL
#define debug(x) cout << "[" __FUNCTION__ ": " #x " = " << (x) << "]\n"
#define TIME cout << "RuningTime: " << clock() << "ms\n", 0
#else
#define TIME 0
#endif
#define hash_ 1000000009
#define Continue(x) { x; continue; }
#define Break(x) { x; break; }
ll fpow(ll a, int b, int mod) { ll res = 1; for (; b > 0; b >>= 1) { if (b & 1) res = res * a % mod; a = a * a % mod; } return res % mod; }
const int mod = 1e9 + 7;
const int N = 2e5 + 100;
#define gc p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
inline int read(){ static char buf[1000000], *p1 = buf, *p2 = buf; register int x = false; register char ch = gc; register bool sgn = false; while (ch != '-' && (ch < '0' || ch > '9')) ch = gc; if (ch == '-') sgn = true, ch = gc; while (ch >= '0'&& ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc; return sgn ? -x : x; }
int mon[N];
int d[N]; //持续i天的最大攻击力
int main()
{
#ifdef LOCAL
	freopen("D:/input.txt", "r", stdin);
#endif
	int t;
	cin >> t;
	while (t--)
	{
		int n, m;
		scanf("%d", &n);
		for (int i = 1; i <= n; i++)
			scanf("%d", &mon[i]);
		scanf("%d", &m);
		for (int i = 1; i <= m; i++)
		{
			int a, b;
			scanf("%d%d", &a, &b);
			d[b] = max(a, d[b]);
		}
		for (int i = n; i >= 0; i--)
			d[i] = max(d[i + 1], d[i]);
		int ans = 0;
		for (int i = 1; i <= n;)
		{
			if (mon[i] > d[1])
			{
				cout << "-1" << endl;
				goto brk;
			}
			int j = 0;
			int MX = 0;
			for (; j <= n; j++) // 枚举天数
			{
				MX = max(MX, mon[i + j]);
				if (d[j + 1] < MX)
					break;
			}
			ans++;
			i += j;
		}
		cout << ans << endl;
	brk:;
		for (int i = 0; i <= n; i++)
			d[i] = 0;
	}
	return TIME;
}

E - The Contest

A team of three programmers is going to play a contest. The contest consists of nn problems, numbered from 11 to nn. Each problem is printed on a separate sheet of paper. The participants have decided to divide the problem statements into three parts: the first programmer took some prefix of the statements (some number of first paper sheets), the third contestant took some suffix of the statements (some number of last paper sheets), and the second contestant took all remaining problems. But something went wrong — the statements were printed in the wrong order, so the contestants have received the problems in some random order.

The first contestant has received problems a1,1,a1,2,…,a1,k1a1,1,a1,2,…,a1,k1. The second one has received problems a2,1,a2,2,…,a2,k2a2,1,a2,2,…,a2,k2. The third one has received all remaining problems (a3,1,a3,2,…,a3,k3a3,1,a3,2,…,a3,k3).

The contestants don't want to play the contest before they redistribute the statements. They want to redistribute them so that the first contestant receives some prefix of the problemset, the third contestant receives some suffix of the problemset, and the second contestant receives all the remaining problems.

During one move, some contestant may give one of their problems to other contestant. What is the minimum number of moves required to redistribute the problems?

It is possible that after redistribution some participant (or even two of them) will not have any problems.

题意:分别给出长度为n,m,k的a,b,c的序列,序列中的元素为[1, n + m + k]的不同数字。

每一次操作可以从一个序列中拿出一个数放到另一个序列,代价为1.

问最少代价使得a序列的元素为1~n+m+k的一个前缀,c为一个后缀,b为中间一个序列。

某个序列可以为空。

思路:设d[i][j]表示第i个数字属于序列j的最小代价。

所以可以得出

d[i][1] = d[i - 1][1] + 1

d[i][2] = min(d[i - 1][1], d[i - 1][2]) + 1

d[i][3] = min(d[i-1][1],d[i -1][2],d[i-1][3])+1

再记录个vis数组,如果当前数字i属于第j个序列,d[i][j]--

最后取个min就行了

#include <iostream>
#include <algorithm>
#include <ctime>
#include <cstdio>
#include <bits/stdc++.h>
//#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

#ifdef LOCAL
#define debug(x) cout << "[" __FUNCTION__ ": " #x " = " << (x) << "]\n"
#define TIME cout << "RuningTime: " << clock() << "ms\n", 0
#else
#define TIME 0
#endif
#define hash_ 1000000009
#define Continue(x) { x; continue; }
#define Break(x) { x; break; }
ll fpow(ll a, int b, int mod) { ll res = 1; for (; b > 0; b >>= 1) { if (b & 1) res = res * a % mod; a = a * a % mod; } return res % mod; }
const int mod = 1e9 + 7;
const int N = 2e5 + 100;
#define gc p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
inline int read(){ static char buf[1000000], *p1 = buf, *p2 = buf; register int x = false; register char ch = gc; register bool sgn = false; while (ch != '-' && (ch < '0' || ch > '9')) ch = gc; if (ch == '-') sgn = true, ch = gc; while (ch >= '0'&& ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc; return sgn ? -x : x; }
int a[N];
int vis[N];
int d[N][4];
int main()
{
#ifdef LOCAL
	freopen("D:/input.txt", "r", stdin);
#endif
	int n, m, k;
	scanf("%d%d%d", &n, &m, &k);
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]), vis[a[i]] = 1;
	for (int i = n + 1; i <= n + m; i++)
		scanf("%d", &a[i]), vis[a[i]] = 2;
	for (int i = n + m + 1; i <= n + m + k; i++)
		scanf("%d", &a[i]), vis[a[i]] = 3;
	n += m + k;
	for (int i = 1; i <= n; i++)
	{
		d[i][1] = d[i - 1][1] + 1;
		d[i][2] = min(d[i - 1][1], d[i - 1][2]) + 1;
		d[i][3] = min({ d[i - 1][1], d[i - 1][2], d[i - 1][3] }) + 1;
		d[i][vis[i]]--;
	}
	cout << min({ d[n][1], d[n][2], d[n][3] }) << endl;
	return TIME;
}

F - Make Them Similar

Let's call two numbers similar if their binary representations contain the same number of digits equal to 11. For example:

  • 22 and 44 are similar (binary representations are 1010 and 100100);
  • 13371337 and 42134213 are similar (binary representations are 1010011100110100111001 and 10000011101011000001110101);
  • 33 and 22 are not similar (binary representations are 1111 and 1010);
  • 4242 and 1313 are similar (binary representations are 101010101010 and 11011101).

You are given an array of nn integers a1a1, a2a2, ..., anan. You may choose a non-negative integer xx, and then get another array of nn integers b1b1, b2b2, ..., bnbn, where bi=ai⊕xbi=ai⊕x (⊕⊕ denotes bitwise XOR).

Is it possible to obtain an array bb where all numbers are similar to each other?

题意给出一个数组a,让你找到一个数字满足异或完每个数后得到的数相似,相似的定义就是二进制位中

1的个数相同, 这题可以折半枚举,先枚举答案的前15位,记录每个数字前15位异或完后含有多少多少个

1,再枚举后十五位,每次枚举再枚举答案异或完这些数字后这些数字含有多少个1,再在枚举的前15位中

查询是否有满足条件的输出即可,最后如果没有就是-1。时间复杂度O(30 * 2^{15})

#include <iostream>
#include <algorithm>
#include <ctime>
#include <cstdio>
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

#ifdef LOCAL
#define debug(x) cout << "[" __FUNCTION__ ": " #x " = " << (x) << "]\n"
#define TIME cout << "RuningTime: " << clock() << "ms\n", 0
#else
#define TIME 0
#endif
#define hash_ 1000000009
#define Continue(x) { x; continue; }
#define Break(x) { x; break; }
ll fpow(ll a, int b, int mod) { ll res = 1; for (; b > 0; b >>= 1) { if (b & 1) res = res * a % mod; a = a * a % mod; } return res % mod; }
const int mod = 1e9 + 7;
const int N = 110;
#define gc p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
inline int read(){ static char buf[1000000], *p1 = buf, *p2 = buf; register int x = false; register char ch = gc; register bool sgn = false; while (ch != '-' && (ch < '0' || ch > '9')) ch = gc; if (ch == '-') sgn = true, ch = gc; while (ch >= '0'&& ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc; return sgn ? -x : x; }
int a[N];
int b[20];
int ans1[N];
int n;
int flag = 0;
map<vector<int>, int>mp;
void dfs1(int d)
{
	if (d == 16)
	{
		vector<int>v;
		int num = 0;
		for (int i = 1; i <= 15; i++)
			num = num * 2 + b[i];
		for (int i = 1; i <= n; i++)
		{
			int sum = 0;
			for (int j = 1; j <= 15; j++)
			{
				if (((a[i] >> (30 - j)) & 1) ^ b[j])
						++sum;		
			}
			v.push_back(sum);
		}
		if (mp.find(v) == mp.end())
			mp[v] = num;
	}
	else
	{
		for (int i = 0; i <= 1; i++)
		{
			b[d] = i;
			dfs1(d + 1);
		}
	}
}
void dfs2(int d)
{
	if (flag)
		return;
	if (d == 16)
	{
		vector<int>v;
		int MX = 0;
		for (int i = 1; i <= n; i++)
		{
			int sum = 0;
			for (int j = 1; j <= 15; j++)
			{
				int x = ((a[i] >> (15 - j)) & 1) ^ b[j];
				if (x)
					++sum;
			}
			v.push_back(sum);
			if (sum > MX)
				MX = sum;
		}
		for (int i = MX; i <= 30; i++)
		{
			vector<int>G;
			for (int j = 1; j <= n; j++)
			{
				G.push_back(i - v[j - 1]);
			}
			if (mp.find(G) != mp.end())
			{
				int num = 0;
				for (int j = 1; j <= 15; j++)
				{
					num = num * 2 + b[j];
			 	}
				flag = 1;
				cout << (mp[G] << 15) + num << endl;
				return;
			}
		}
	}
	else
	{
		for (int i = 0; i <= 1; i++)
		{
			b[d] = i;
			dfs2(d + 1);
		}
	}
}
int main()
{
#ifdef LOCAL
	freopen("D:/input.txt", "r", stdin);
#endif
	scanf("%d", &n);
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);
	dfs1(1);
	memset(b, 0, sizeof b);
	dfs2(1);
	if (!flag)
		cout << -1 << endl;
	return TIME;
}

猜你喜欢

转载自blog.csdn.net/weixin_43731933/article/details/103101476