Codeforces Round #637 (Div. 2) 题解

A. Nastya and Rice

网址:https://codeforces.com/contest/1341/problem/A

Nastya just made a huge mistake and dropped a whole package of rice on the floor. Mom will come soon. If she sees this, then Nastya will be punished.

In total, Nastya dropped n grains. Nastya read that each grain weighs some integer number of grams from a−b to a+b, inclusive (numbers a and b are known), and the whole package of n grains weighs from c−d to c+d grams, inclusive (numbers c and d are known). The weight of the package is the sum of the weights of all n grains in it.

Help Nastya understand if this information can be correct. In other words, check whether each grain can have such a mass that the i-th grain weighs some integer number xi (a−b≤xi≤a+b), and in total they weigh from c−d to c+d, inclusive

(c−d≤sum{xi | 1 <= i <= n}≤c+d).

Input

The input consists of multiple test cases. The first line contains a single integer t (1≤t≤1000) — the number of test cases.

The next t lines contain descriptions of the test cases, each line contains 5 integers: n (1≤n≤1000) — the number of grains that Nastya counted and a,b,c,d (0≤b<a≤1000,0≤d<c≤1000) — numbers that determine the possible weight of one grain of rice (from a−b to a+b) and the possible total weight of the package (from c−d to c+d).

Output

For each test case given in the input print "Yes", if the information about the weights is not inconsistent, and print "No" if n grains with masses from a−b to a+b cannot make a package with a total mass from c−d to c+d.

Example
input
5
7 20 3 101 18
11 11 10 234 2
8 9 7 250 122
19 41 21 321 10
3 10 8 6 1
output
Yes
No
Yes
No
Yes
Note

In the first test case of the example, we can assume that each grain weighs 17 grams, and a pack 119 grams, then really Nastya could collect the whole pack.

In the third test case of the example, we can assume that each grain weighs 16 grams, and a pack 128 grams, then really Nastya could collect the whole pack.

In the fifth test case of the example, we can be assumed that 3 grains of rice weigh 2, 2, and 3 grams, and a pack is 7 grams, then really Nastya could collect the whole pack.

In the second and fourth test cases of the example, we can prove that it is impossible to determine the correct weight of all grains of rice and the weight of the pack so that the weight of the pack is equal to the total weight of all collected grains.

上下界确定即可。

代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int n, a, b, c, d;
int main()
{
	int T, vmin, vmax;
	scanf("%d", &T);
	while(T --)
	{
		vmin = 0, vmax = 0;
		scanf("%d %d %d %d %d", &n, &a, &b, &c, &d);
		vmin = n * (a - b), vmax = n * (a + b);
		if(vmin <= c + d && vmax >= c - d) puts("Yes");
		else puts("No");
	}
	return 0;
}

B. Nastya and Door

网址:https://codeforces.com/contest/1341/problem/B

On February 14 Denis decided to give Valentine to Nastya and did not come up with anything better than to draw a huge red heart on the door of the length k (k≥3). Nastya was very confused by this present, so she decided to break the door, throwing it on the mountains.

Mountains are described by a sequence of heights a1,a2,…,an in order from left to right (k≤n). It is guaranteed that neighboring heights are not equal to each other (that is, ai≠ai+1 for all i from 1 to n−1).

Peaks of mountains on the segment [l,r] (from l to r) are called indexes i such that l<i<r, ai−1ai+1. It is worth noting that the boundary indexes l and r for the segment are not peaks. For example, if n=8 and a=[3,1,4,1,5,9,2,6], then the segment [1,8] has only two peaks (with indexes 3 and 6), and there are no peaks on the segment [3,6].

To break the door, Nastya throws it to a segment [l,l+k−1] of consecutive mountains of length k (1≤l≤n−k+1). When the door touches the peaks of the mountains, it breaks into two parts, after that these parts will continue to fall in different halves and also break into pieces when touching the peaks of the mountains, and so on. Formally, the number of parts that the door will break into will be equal to p+1, where p is the number of peaks on the segment [l,l+k−1].

Nastya wants to break it into as many pieces as possible. Help her choose such a segment of mountains [l,l+k−1] that the number of peaks on it is maximum. If there are several optimal segments, Nastya wants to find one for which the value l is minimal.

Formally, you need to choose a segment of mountains [l,l+k−1] that has the maximum number of peaks. Among all such segments, you need to find the segment that has the minimum possible value l.

Input

The first line contains an integer t (1≤t≤(10^4)) — the number of test cases. Then the descriptions of the test cases follow.

The first line of each test case contains two integers n and k (3≤k≤n≤(2⋅10^5)) — the number of mountains and the length of the door.

The second line of the input data set contains n integers a1,a2,…,an (0≤ai≤(10^9), ai≠ai+1) — the heights of mountains.

It is guaranteed that the sum of n over all the test cases will not exceed (2⋅10^5).

Output

For each test case, output two integers t and l — the maximum number of parts that the door can split into, and the left border of the segment of length k that the door should be reset to.

Example
input
5
8 6
1 2 4 1 2 4 1 2
5 3
3 2 3 2 1
10 4
4 3 4 3 2 3 2 1 0 1
15 7
3 7 4 8 2 3 4 5 21 2 3 4 2 1 3
7 5
1 2 3 4 5 6 1
output
3 2
2 2
2 1
3 1
2 3
Note

In the first example, you need to select a segment of mountains from 2 to 7. In this segment, the indexes 3 and 6 are peaks, so the answer is 3 (only 2 peaks, so the door will break into 3 parts). It is not difficult to notice that the mountain segments [1,6] and [3,8] are not suitable since they only have a 1 peak (for the first segment, the 6 index is not a peak, and for the second segment, the 3 index is not a peak).

In the second example, you need to select a segment of mountains from 2 to 4. In this segment, the index 3 is a peak, so the answer is 2 (only 1 peak, so the door will break into 2 parts).

In the third example, you need to select a segment of mountains from 1 to 4. In this segment, the index 3 is a peak, so the answer is 2 (only 1 peak, so the door will break into 2 parts). You can see that on the segments [2,5], [4,7] and [5,8] the number of peaks is also 1, but these segments have a left border greater than the segment [1,4], so they are not the correct answer.

题目概括:定义“顶”:对于任意一个i,若满足a[i] > a[i - 1] 与 a[i] > a[i + 1],则称i为“顶点”。给定区间长度为k,要求滑动窗口,统计[L,L + k - 1]中“顶点”个数(不含区间端点),“顶点”个数最多且左端点下标最小的的区间,输出该区间的L和共有的“顶点”个数。

花O(n)统计每个位置是否是“顶”,枚举区间更新即可(一定留意:不含区间端点!!)。

代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn = 200000 + 15;
bool b[maxn];
int n, k, a[maxn]; 
int s[maxn] = {};
int main()
{
	int T;
	scanf("%d", &T);
	while(T --)
	{
		memset(a, 0, sizeof(a));
		memset(s, 0, sizeof(s));
		memset(b, false, sizeof(b));
		
		scanf("%d %d", &n, &k);
		for(int i = 1; i <= n; ++ i) scanf("%d", &a[i]);
		for(int i = 2; i <= n - 1; ++ i)
		{
			s[i] = s[i - 1];
			if(a[i] > a[i - 1] && a[i] > a[i + 1])
			{
				++ s[i];
				b[i] = true;
			}
		}
		int L = 1, val = -1;
		for(int i = 1; i <= n; ++ i)
		{
			if(i + k > n + 1) break;
			if(val < s[i + k - 2] - s[i])
			{
				L = i;
				val = s[i + k - 2] - s[i];
			}
		}
		printf("%d %d
", val + 1, L);
	}
	return 0;
}

C. Nastya and Strange Generator

网址:https://codeforces.com/contest/1341/problem/C

Denis was very sad after Nastya rejected him. So he decided to walk through the gateways to have some fun. And luck smiled at him! When he entered the first courtyard, he met a strange man who was selling something.

Denis bought a mysterious item and it was... Random permutation generator! Denis could not believed his luck.

When he arrived home, he began to study how his generator works and learned the algorithm. The process of generating a permutation consists of n steps. At the i-th step, a place is chosen for the number i (1≤i≤n). The position for the number i is defined as follows:

For all j from 1 to n, we calculate rj — the minimum index such that j≤rj≤n, and the position rj is not yet occupied in the permutation. If there are no such positions, then we assume that the value of rj is not defined.
For all t from 1 to n, we calculate countt — the number of positions 1≤j≤n such that rj is defined and rj=t.
Consider the positions that are still not occupied by permutation and among those we consider the positions for which the value in the count array is maximum.
The generator selects one of these positions for the number i. The generator can choose any position.
Let's have a look at the operation of the algorithm in the following example:
image
Let n=5 and the algorithm has already arranged the numbers 1,2,3 in the permutation. Consider how the generator will choose a position for the number 4:

The values of r will be r=[3,3,3,4,×], where × means an indefinite value.
Then the count values will be count=[0,0,3,1,0].
There are only two unoccupied positions in the permutation: 3 and 4. The value in the count array for position 3 is 3, for position 4 it is 1.
The maximum value is reached only for position 3, so the algorithm will uniquely select this position for number 4.
Satisfied with his purchase, Denis went home. For several days without a break, he generated permutations. He believes that he can come up with random permutations no worse than a generator. After that, he wrote out the first permutation that came to mind p1,p2,…,pn and decided to find out if it could be obtained as a result of the generator.

Unfortunately, this task was too difficult for him, and he asked you for help. It is necessary to define whether the written permutation could be obtained using the described algorithm if the generator always selects the position Denis needs.

Input

The first line contains a single integer t(1≤t≤(10^5))
— the number of test cases. Then the descriptions of the test cases follow.

The first line of the test case contains a single integer n(1≤n≤(10^5))
— the size of the permutation.

The second line of the test case contains n different integers p1,p2,…,pn (1≤pi≤n) — the permutation written by Denis.

It is guaranteed that the sum of n over all test cases doesn't exceed 10^5.

Output

Print "Yes" if this permutation could be obtained as a result of the generator. Otherwise, print "No".

All letters can be displayed in any case.

Example
input
5
5
2 3 4 5 1
1
1
3
1 3 2
4
4 2 3 1
5
1 5 2 4 3
output
Yes
Yes
No
Yes
No
Note

Let's simulate the operation of the generator in the first test.

At the 1 step, r=[1,2,3,4,5],count=[1,1,1,1,1]. The maximum value is reached in any free position, so the generator can choose a random position from 1 to 5. In our example, it chose 5.

At the 2 step, r=[1,2,3,4,×],count=[1,1,1,1,0]. The maximum value is reached in positions from 1 to 4, so the generator can choose a random position among them. In our example, it chose 1.

At the 3 step, r=[2,2,3,4,×],count=[0,2,1,1,0]. The maximum value is 2 and is reached only at the 2 position, so the generator will choose this position.

At the 4 step, r=[3,3,3,4,×],count=[0,0,3,1,0]. The maximum value is 3 and is reached only at the 3 position, so the generator will choose this position.

At the 5 step, r=[4,4,4,4,×],count=[0,0,0,4,0]. The maximum value is 4 and is reached only at the 4 position, so the generator will choose this position.

In total, we got a permutation of 2,3,4,5,1, that is, a generator could generate it.

题意概括:一个序列生成器按照规则生成序列:依次考虑1~n,对于每个数i,我们为其选择在生成序列中位置,有生成的规则:

  • 生成一个数组r,第j个数的值记作r[j],满足:j <= r[j] <= n,且当前生成序列当中(没有完全生成好,也就是有的位置没有生成的数),第r[j]个位置必须保证没有数生成(换句话说,若在先前操作中该位置已经填上了数了,那么r[j]不可以是该位置的下标),同时r[j]须越小越好(如果3、4和5均可,则选择3,因为值最小)。
  • 再生成count数组,记录r数组中每一个值的个数。譬如:r[3] = {2, 2, 3},则count[4] = {0, 2, 1}(统计出现次数)。
  • 言归正传,在生成环节结束后(r和count数组生成完毕了),对于i生成的位置,该位置为count数组中数最大的位置的下标(如果count[4]最大,该数应填在生成序列中的第四个),若有多个位置下的值满足,则在其中选择任意一个位置。
    给定一个序列p,求是否可以按上述规律生成p。

题意挺绕,只要静心模拟一下,变可以发现规律:题目其实就是想问区间是否“连续”。
称这样的序列为“连续”:456|123、123456、89|567|1234。(留意分出的子序列的共同点)而这样的序列:
123465、41235、132则不满足题意。

代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 100000 + 10;
bool valid;
int n, p[maxn], a[maxn], head, tail;
int main()
{
	int T;
	scanf("%d", &T);
	while(T --)
	{
		scanf("%d", &n);
		for(int i = 1; i <= n; ++ i)
		{
			scanf("%d", &p[i]);
			a[p[i]] = i;
		}
		head = a[1], tail = n;
		valid = true;
		for(int i = 1; i <= n; ++ i)
		{
			if(a[i] != a[i - 1] + 1 && a[i] != head)
			{
				valid = false;
				break;
			}
			if(a[i] == tail)
			{
				tail = head - 1;
				head = a[i + 1];
			}
		}
		if(valid) puts("Yes");
		else puts("No");
	}
	return 0;
}

D. Nastya and Scoreboard

网址:https://codeforces.com/contest/1341/problem/D

Denis, after buying flowers and sweets (you will learn about this story in the next task), went to a date with Nastya to ask her to become a couple. Now, they are sitting in the cafe and finally... Denis asks her to be together, but ... Nastya doesn't give any answer.

The poor boy was very upset because of that. He was so sad that he punched some kind of scoreboard with numbers. The numbers are displayed in the same way as on an electronic clock: each digit position consists of 7 segments, which can be turned on or off to display different numbers. The picture shows how all 10 decimal digits are displayed:
image

After the punch, some segments stopped working, that is, some segments might stop glowing if they glowed earlier. But Denis remembered how many sticks were glowing and how many are glowing now. Denis broke exactly k segments and he knows which sticks are working now. Denis came up with the question: what is the maximum possible number that can appear on the board if you turn on exactly k sticks (which are off now)?

It is allowed that the number includes leading zeros.

Input

The first line contains integer n (1≤n≤2000) — the number of digits on scoreboard and k (0≤k≤2000) — the number of segments that stopped working.

The next n lines contain one binary string of length 7, the i-th of which encodes the i-th digit of the scoreboard.

Each digit on the scoreboard consists of 7 segments. We number them, as in the picture below, and let the i-th place of the binary string be 0 if the i-th stick is not glowing and 1 if it is glowing. Then a binary string of length 7 will specify which segments are glowing now.
image
Thus, the sequences "1110111", "0010010", "1011101", "1011011", "0111010", "1101011", "1101111", "1010010", "1111111", "1111011" encode in sequence all digits from 0 to 9 inclusive.

Output

Output a single number consisting of n digits — the maximum number that can be obtained if you turn on exactly k sticks or −1, if it is impossible to turn on exactly k sticks so that a correct number appears on the scoreboard digits.

Examples
input
1 7
0000000
output
8
input
2 5
0010010
0010010
output
97
input
3 5
0100001
1001001
1010011
output
-1
Note

In the first test, we are obliged to include all 7 sticks and get one 8 digit on the scoreboard.

In the second test, we have sticks turned on so that units are formed. For 5 of additionally included sticks, you can get the numbers 07, 18, 34, 43, 70, 79, 81 and 97, of which we choose the maximum — 97.

In the third test, it is impossible to turn on exactly 5 sticks so that a sequence of numbers appears on the scoreboard.

这道题我使用将每个数码亮灯情况转化为二进制数(预处理十个数码的状态),状态压缩,记忆化搜索。

留意:算状态A亮多少盏灯变成状态B,不可直接把两个数异或运算,因为A中有些灯需要熄灭才能成为B,而这不合题意。

代码如下:

#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn = 2000 + 5;
const int d_code[10] = {119, 18, 93, 91, 58, 107, 111, 82, 127, 123};//预处理十个数码
int n, k, p[maxn], d[maxn][maxn] = {-1};
vector <int> a;
int calc(int x, int y)
{
	int T = 0;
	for(int i = 0; i < 7; ++ i)
	{
		if(y & (1 << i) && !(x & (1 << i))) return -1;
		if(x & (1 << i) && !(y & (1 << i))) ++ T;
	}
	return T;
}
bool dfs(int cur, int m)
{
	if(cur == n)
	{
		if(m > 0) return false;
		for(int i = 0; i < a.size(); ++ i) printf("%d", a[i]);
		puts("");
		return true;
	}
	int &ans = d[cur][m];
	if(ans != -1) return ans;//记忆化
	bool ok = false;
	for(int i = 9; i >= 0; -- i)
	{
		int num = calc(d_code[i], p[cur]);
		if(num == -1) continue;
		if(num > m) continue;
		a.push_back(i);
		ok = dfs(cur + 1, m - num);
		a.pop_back();
		if(ok) return ans = 1;
	}
	return ans = 0;
}
int main()
{
	memset(d, -1, sizeof(d));
	memset(p, 0, sizeof(p));
	a.clear();
	scanf("%d %d", &n, &k);
	for(int i = 0; i < n; ++ i)
	{
		int op;
		for(int j = 0; j < 7; ++ j)
		{
			scanf("%1d", &op);
			p[i] = (p[i] << 1) + op;
		}
	}
	if(!dfs(0, k)) puts("-1");
	return 0;
}

本题有DP做法:预处理cnt[i, j]代表第i个数码初始状态变成数字j所需要亮灯的数量(熄灯不可以),dp[i, j]代表考虑第i个数码到剩余数码时,还需要严格的点亮j盏灯的可行性。
dp[i, j] |= dp[i - 1, j - cnt[i][x]]。我的代码中将整个数码顺序颠倒下。

最后结果:贪心也可以,利用dp数组逆推也行(我代码采用这一种方式)。

代码如下:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 2000 + 5;
const int d_code[10] = {119, 18, 93, 91, 58, 107, 111, 82, 127, 123};
int n, k, p[maxn], cnt[maxn][10], f[maxn][maxn];
bool dp[maxn][maxn];

int calc(int x, int y)
{
	int T = 0;
	for(int i = 0; i < 7; ++ i)
	{
		//当前状态下的某位 亮灯 但是目标在该位置下 没有亮灯,就不符合题意。 
		if(y & (1 << i) && !(x & (1 << i))) return 2505;//如果赋INF啦,会WA 
		if(x & (1 << i) && !(y & (1 << i))) ++ T;
	}
	return T;
}
int main()
{
	memset(p, 0, sizeof(p)); 
	memset(dp, false, sizeof(dp));
	scanf("%d %d", &n, &k);
	for(int i = 1; i <= n; ++ i)
	{
		int op;
		for(int j = 0; j < 7; ++ j)
		{
			scanf("%1d", &op);
			p[i] = (p[i] << 1) + op;
		}
	}
	reverse(p + 1, p + n + 1);
	for(int i = 1; i <= n; ++ i)
		for(int j = 0; j < 10; ++ j) cnt[i][j] = calc(d_code[j], p[i]);
	
	dp[0][0] = true;
	for(int i = 1; i <= n; ++ i)
	{
		for(int j = 0; j <= k; ++ j)
		{
			for(int x = 0; x < 10; ++ x)
			{
				if(j >= cnt[i][x])
				{
					dp[i][j] |= dp[i - 1][j - cnt[i][x]];
					if(dp[i - 1][j - cnt[i][x]]) f[i][j] = x;
				}
			}
		}
	}
	if(dp[n][k])
	{
		int now = k;
		for(int i = n; i > 0; -- i)
		{
			printf("%d", f[i][now]);
			now -= cnt[i][f[i][now]];
		}
	}
	else puts("-1");
	return 0;
}
原文地址:https://www.cnblogs.com/zach20040914/p/12827977.html