Codeforces Round #656 (Div. 3)题解总结


来源: http://codeforces.com/contest/1385

A. Three Pairwise Maximums

You are given three positive (i.e. strictly greater than zero) integers x, y and z.

Your task is to find positive integers a, b and c such that x=max(a,b), y=max(a,c) and z=max(b,c), or determine that it is impossible to find such a, b and c.

You have to answer t independent test cases. Print required a, b and c in any (arbitrary) order.

Input
The first line of the input contains one integer t (1≤t≤2⋅104) — the number of test cases. Then t test cases follow.

The only line of the test case contains three integers x, y, and z (1≤x,y,z≤109).

Output
For each test case, print the answer:

“NO” in the only line of the output if a solution doesn’t exist;
or “YES” in the first line and any valid triple of positive integers a, b and c (1≤a,b,c≤109) in the second line. You can print a, b and c in any order.
Example
inputCopy
5
3 2 3
100 100 100
50 49 49
10 30 20
1 1000000000 1000000000
outputCopy
YES
3 2 1
YES
100 100 100
NO
NO
YES
1 1 1000000000

题意:
给你三个正整数x、y和z,请你找到正整数a,b和c,使得x=max(a,b),y=max(a,c)且z=max(b,c),或者确定不可能找到这样的a,b和c(你可以以任意顺序输出a,b,c)

思路:
因为x=max(a,b),y=max(a,c)x且z=max(b,c),我们可以得出x,y,z中至少有两个数是相等的,且一定大于等于另一个数
如果x=y则说明a为最大值,此时需要满足a>=z,如果不满足该条件,则无解,因为z=max(b,c),我们不能确定b,c谁比较大,所以我们就假设两个数一样的即可。
x=z时和y=z时同理

代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<cstdio>
using namespace std;
typedef long long ll;
int inf = 0x3f3f3f3f;
const ll N = 2e6+5;
int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
		int a = 0, b = 0, c = 0, x, y, z;
		cin >> x >> y >> z;
		if (x == y) a = x;
		else if (y == z) c = y;
		else if (x == z) b = x;
		if ((a && a >= z) || (b && b >= y) || (c && c >= x)) 
		{
			cout << "YES" << endl;
			if (a) cout << a << " " << z << " " << z << endl;
			else if (b) cout << b << " " << y << " " << y << endl;
			else if (c) cout << c << " " << x << " " << x << endl;
		}
		else
			cout << "NO" << endl;
    }
    return 0;
}

B. Restore the Permutation by Merger

A permutation of length n is a sequence of integers from 1 to n of length n containing each number exactly once. For example, [1], [4,3,5,1,2], [3,2,1] are permutations, and [1,1], [0,1], [2,2,1,4] are not.

There was a permutation p[1…n]. It was merged with itself. In other words, let’s take two instances of p and insert elements of the second p into the first maintaining relative order of elements. The result is a sequence of the length 2n.

For example, if p=[3,1,2] some possible results are: [3,1,2,3,1,2], [3,3,1,1,2,2], [3,1,3,1,2,2]. The following sequences are not possible results of a merging: [1,3,2,1,2,3], [3,1,2,3,2,1], [3,3,1,2,2,1].

For example, if p=[2,1] the possible results are: [2,2,1,1], [2,1,2,1]. The following sequences are not possible results of a merging: [1,1,2,2], [2,1,1,2], [1,2,2,1].

Your task is to restore the permutation p by the given resulting sequence a. It is guaranteed that the answer exists and is unique.

You have to answer t independent test cases.

Input
The first line of the input contains one integer t (1≤t≤400) — the number of test cases. Then t test cases follow.

The first line of the test case contains one integer n (1≤n≤50) — the length of permutation. The second line of the test case contains 2n integers a1,a2,…,a2n (1≤ai≤n), where ai is the i-th element of a. It is guaranteed that the array a represents the result of merging of some permutation p with the same permutation p.

Output
For each test case, print the answer: n integers p1,p2,…,pn (1≤pi≤n), representing the initial permutation. It is guaranteed that the answer exists and is unique.

Example
inputCopy
5
2
1 1 2 2
4
1 3 1 4 3 4 2 2
5
1 2 1 2 3 4 3 5 4 5
3
1 2 3 1 2 3
4
2 3 2 4 1 3 4 1
outputCopy
1 2
1 3 4 2
1 2 3 4 5
1 2 3
2 3 4 1

题意:
有一种排列p,将第二个p的元素插入到第一个保持相对顺序的元素中,结果是长度为2n的序列a,现给你插入后的序列a,请你求出原序列p

思路
因为是保持相对顺序插入的,所以我们直接遍历序列a找排列即可
因为排列中不能有重复的元素,为了方便我们可以将已经输出的元素存入set,用s.count(a[i])判断已经确定的p序列中是否已经有a[i]元素,s.size()==n时说明p排列中所有元素都已经确定,退出循环即可
代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<set>
using namespace std;
typedef long long ll;
int inf = 0x3f3f3f3f;
const ll N = 2e6+5;
int a[55];
int main()
{
    int t;
    scanf("%d", &t);
    while (t--)
    {
		int n;
		cin >> n;
		set<int> s;
		for (int i = 1; i <= 2 * n; i++)
			cin >> a[i];
		for (int i = 1; i <= 2 * n; i++) {
			if (!s.count(a[i])) {
				cout << a[i] << " ";
				s.insert(a[i]);
			}
			if (s.size() == n) break;
		}
    }
    return 0;
}

C. Make It Good

time limit per test1 second
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given an array a consisting of n integers. You have to find the length of the smallest (shortest) prefix of elements you need to erase from a to make it a good array. Recall that the prefix of the array a=[a1,a2,…,an] is a subarray consisting several first elements: the prefix of the array a of length k is the array [a1,a2,…,ak] (0≤k≤n).

The array b of length m is called good, if you can obtain a non-decreasing array c (c1≤c2≤⋯≤cm) from it, repeating the following operation m times (initially, c is empty):

select either the first or the last element of b, remove it from b, and append it to the end of the array c.
For example, if we do 4 operations: take b1, then bm, then bm−1 and at last b2, then b becomes [b3,b4,…,bm−3] and c=[b1,bm,bm−1,b2].

Consider the following example: b=[1,2,3,4,4,2,1]. This array is good because we can obtain non-decreasing array c from it by the following sequence of operations:

take the first element of b, so b=[2,3,4,4,2,1], c=[1];
take the last element of b, so b=[2,3,4,4,2], c=[1,1];
take the last element of b, so b=[2,3,4,4], c=[1,1,2];
take the first element of b, so b=[3,4,4], c=[1,1,2,2];
take the first element of b, so b=[4,4], c=[1,1,2,2,3];
take the last element of b, so b=[4], c=[1,1,2,2,3,4];
take the only element of b, so b=[], c=[1,1,2,2,3,4,4] — c is non-decreasing.
Note that the array consisting of one element is good.

Print the length of the shortest prefix of a to delete (erase), to make a to be a good array. Note that the required length can be 0.

You have to answer t independent test cases.

Input
The first line of the input contains one integer t (1≤t≤2⋅104) — the number of test cases. Then t test cases follow.

The first line of the test case contains one integer n (1≤n≤2⋅105) — the length of a. The second line of the test case contains n integers a1,a2,…,an (1≤ai≤2⋅105), where ai is the i-th element of a.

It is guaranteed that the sum of n does not exceed 2⋅105 (∑n≤2⋅105).

Output
For each test case, print the answer: the length of the shortest prefix of elements you need to erase from a to make it a good array.

Example
inputCopy
5
4
1 2 3 4
7
4 3 3 8 4 5 2
3
1 1 1
7
1 3 1 4 5 3 2
5
5 4 3 2 3
outputCopy
0
4
0
2
3
Note
In the first test case of the example, the array a is already good, so we don’t need to erase any prefix.

In the second test case of the example, the initial array a is not good. Let’s erase first 4 elements of a, the result is [4,5,2]. The resulting array is good. You can prove that if you erase fewer number of first elements, the result will not be good.

题意:
如果能通过以下操作,从数组 b 中获得一个非递减的数组 c,则成数组 b 为好。选择 b的第一个或最后一个元素,将其从 b 中删除,并将其附加到数组 c的末尾。

思路:
仔细观察以下题面给的样例,从后向前找一个连续的非减然后非增序列长度。即找到第一个不满足从后往前递增条件的元素,然后从这个元素往前找到开始升的那个元素就停止,答案就是n减去最长“好序列”长度。

代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<set>
using namespace std;
typedef long long ll;
int inf = 0x3f3f3f3f;
const ll N = 2e5 + 5;
int a[N];
int main()
{
    int t;
    cin >> t;
    while (t--)
    {
        int n;
        cin >> n;
        for (int i = 1; i <= n; i++) 
            cin >> a[i];
        int r = n;
        while (a[r - 1] >= a[r] && r >= 1) 
            r--;
        while (a[r - 1] <= a[r] && r >= 1)
            r--;
        int ans = r - 1;
        if (ans == -1) 
            ans = 0;
        cout << ans << endl;
    }
    return 0;
}

D. a-Good String

time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given a string s[1…n] consisting of lowercase Latin letters. It is guaranteed that n=2k for some integer k≥0.

The string s[1…n] is called c-good if at least one of the following three conditions is satisfied:

The length of s is 1, and it consists of the character c (i.e. s1=c);
The length of s is greater than 1, the first half of the string consists of only the character c (i.e. s1=s2=⋯=sn2=c) and the second half of the string (i.e. the string sn2+1sn2+2…sn) is a (c+1)-good string;
The length of s is greater than 1, the second half of the string consists of only the character c (i.e. sn2+1=sn2+2=⋯=sn=c) and the first half of the string (i.e. the string s1s2…sn2) is a (c+1)-good string.
For example: “aabc” is ‘a’-good, “ffgheeee” is ‘e’-good.

In one move, you can choose one index i from 1 to n and replace si with any lowercase Latin letter (any character from ‘a’ to ‘z’).

Your task is to find the minimum number of moves required to obtain an ‘a’-good string from s (i.e. c-good string for c= ‘a’). It is guaranteed that the answer always exists.

You have to answer t independent test cases.

Another example of an ‘a’-good string is as follows. Consider the string s=“cdbbaaaa”. It is an ‘a’-good string, because:

the second half of the string (“aaaa”) consists of only the character ‘a’;
the first half of the string (“cdbb”) is ‘b’-good string, because:
the second half of the string (“bb”) consists of only the character ‘b’;
the first half of the string (“cd”) is ‘c’-good string, because:
the first half of the string (“c”) consists of only the character ‘c’;
the second half of the string (“d”) is ‘d’-good string.
Input
The first line of the input contains one integer t (1≤t≤2⋅104) — the number of test cases. Then t test cases follow.

The first line of the test case contains one integer n (1≤n≤131 072) — the length of s. It is guaranteed that n=2k for some integer k≥0. The second line of the test case contains the string s consisting of n lowercase Latin letters.

It is guaranteed that the sum of n does not exceed 2⋅105 (∑n≤2⋅105).

Output
For each test case, print the answer — the minimum number of moves required to obtain an ‘a’-good string from s (i.e. c-good string with c= ‘a’). It is guaranteed that the answer exists.

Example
inputCopy
6
8
bbdcaaaa
8
asdfghjk
8
ceaaaabb
8
bbaaddcc
1
z
2
ac
outputCopy
0
7
4
5
1
1
题意:
这是一个递归定义。定义字符串串为 c-good需要满足以下三个条件
若字符串长度为1,则s1=c。
若字符串长度大于1,前半部分s1=s2=s2=sn/2=c 并且后半部分 是(sn/2+1sn/2+2……sn) 是(c+1)-good
若字符串长度大于1,后半部分s1=s2=s2=sn/2=c 并且前半部分 是(sn/2+1sn/2+2……sn) 是(c+1)-good
给你一个字符串,要你判断需要改动字符串多少次,才能够满足上述定义 ‘a’-good

思路:
第一眼看上去像是贪心,但仔细想想又不是。然后又干脆直接暴力找了,每次递归查找一半字符串。因为字符串长度为n,所以每次二分递归下去,最多递归Log(n)次,,加上每次判断需要改动字符数量为n,所以整体复杂度为nlog(n),不会超时。

代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<iomanip>
#include<cstdio>
#include<set>
using namespace std;
typedef long long ll;
int inf = 0x3f3f3f3f;
const ll N = 2e5 + 5;
int a[N];
int check(string str, char ch) 
{
	int i;
	int cnt = 0;
	for (i = 0; i < str.size(); i++)
	{
		if (str[i] != ch)
			cnt++;
	}
	return cnt;
}
int ans = 0;
int solve(string str, char ch, int res) 
{
	if (str.size() == 1)
	{
		if (str[0] != ch)
			return res + 1;
		return res;
	}
	int len = str.size();
	string str1 = str.substr(0, len / 2);
	string str2 = str.substr(len / 2);
	int cnt1 = check(str1, ch);
	int cnt2 = check(str2, ch);

	return min(res + solve(str2, ch + 1, res) + cnt1, res + solve(str1, ch + 1, res) + cnt2);
}

int main()
{
	int t;
	cin >> t;
	while (t--) 
	{
		int n;
		ans = 0;
		cin >> n;
		string str;
		cin >> str;
		ans = solve(str, 'a', 0);
		cout << ans << endl;
	}
	return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值