Educational Codeforces Round 149 (Rated for Div. 2)(A—D、F)

A. Grasshopper on a Line

A. Grasshopper on a Line

1. Problem

Given a nnn andkkk n n n can be written asmmThe sum of m numbers, but the title stipulates that these numbers cannot bekkmultiple of k . Now we need to find the smallestmmm , output thismmm digits.

2. Analysis

if nnn is notkkA multiple of k , here you can directly outputnnn , iem = 1 m=1m=1

if nnn iskkA multiple of k , indicating that we need to usennn to split. A conclusion is given here: for any number nnin this casen , only needs to be split into two numbers.

prove:
because nn iskkMultiples of k , we can assumen = a ∗ kn=a*kn=ak

If a ≥ 2 a\geq 2a2

Then we can make p + q = a p+q=ap+q=a ,则n = ( p + q ) ∗ k = p ∗ k + q ∗ kn=(p+q)*k=p*k+q*kn=(p+q)k=pk+qk , at this point we can letans 1 = p ∗ k + 1 ans_1=p*k+1ans1=pk+1, a n s 2 = q ∗ k − 1 ans_2=q*k-1 ans2=qk1 , because the title stipulates thatk ≥ 2 k \geq 2k2 . So the constructedppp andqqq will not bekkmultiple of k .

if a < 2 a < 2a<2 , immediatelya = 1 a=1a=1 , at this point we can letp = 1 , q = n − 1 p=1,q=n-1p=1,q=n1 is enough.

3. Code

#include<bits/stdc++.h>
using namespace std;

void solve()
{
    
    
	int n, k;
	cin >> n >> k;
	if(n % k != 0)
	{
    
    
		cout << 1 << endl;
		cout << n << endl;
	}
	else
	{
    
    
		cout << 2 << endl;
		int a = n / k;
		if(a == 1)
			cout << 1 << " " << n - 1 << endl;
		else
			cout << (a - 1) * k + 1 << " " << k - 1 << endl;
	}
}

signed main()
{
    
    
	ios::sync_with_stdio(0);
	cin.tie(0);
	int t;
	cin >> t;
	while(t--)
	solve();
}

B. Comparison String

B. Comparison String

1. Problem

Given a given by ′ < ′ '<'< and′ > ′ '>'>' The string S formed by ', where if S[i] means' > ' '>'>' , the corresponding a array needs to satisfy:a [ i ] > a [ i + 1 ] a[i]>a[i+1]a[i]>a[i+1 ] , now please construct an array with the least number, and output the number of different numbers.

2. Analysis

insert image description here
According to the above example, we can see that if '>' or '<' are arranged continuously, the number of our elements will increase. When the opposite sign appears, we can use the number that just appeared to construct it.

It is not difficult to find such a rule through the above examples.
'>' and '<' respectively correspond to the longest continuous substring, and the lengths are recorded as ppp andqqq . Then the answer is:ans = max ( p , q ) + 1 ans=max(p,q)+1ans=max(p,q)+1

3. Code

#include<bits/stdc++.h>
using namespace std;

void solve()
{
    
    
	int n;
	string s;
	cin >> n >> s;
	int ans = 0;
	for(int i = 0; i < n; i ++)
	{
    
    
		int j = i;
		while(j < n && s[j] == s[i])
			j ++;
		ans = max(ans, j - i);
		i = j - 1;
	}
	cout << ans + 1 << endl;
}

signed main()
{
    
    
	ios::sync_with_stdio(0);
	cin.tie(0);
	int t;
	cin >> t;
	while(t--)
	solve();
}

C. Best Binary String

C. Best Binary String

1. Problem

Given a string, this string is composed of 1, 0,? three characters, where we can fill in 0 or 1 in the? part, and each? is independent, that is, a certain? It does not affect the filling selection of subsequent?. Now we need to assign a value to each ? in the string. get a 01 0101 string, then for the01 01The 01 string can be operated as follows: select any continuous substring to reverse. After multiple operations, the string can be sorted into a non-descending string. In this process, a number of operations will be obtained. Now we need to output a minimum number of operations01 0101 string.

2. Analysis

According to the title, after multiple operations, our string will look like this:

insert image description here

That is, we need to put all 1s together and all 0s together.
insert image description here
As can be seen from the above example, as long as there are non-consecutive 1s, we need one operation, that is, how many consecutive 1 strings exist, we need to perform several inversions, soOur purpose is to minimize the number of consecutive 1 substrings

It can be seen from the above conclusion that as long as there is a substring in the form of "1???1" , the question mark in the middle needs to be written as the number 1 .

If it is **"0???1" or "1???0"**, it doesn't matter if all the question marks in the middle are filled with 0 or 1 . Then we can stipulate that if the beginning is 0, write 0, if the beginning is 1, write 1. The purpose of this is to write code better.

If a question mark appears at the beginning "???0", you need to write all 0's if this is the case . Because if we write all 1, the substring of 1 will increase.
If the beginning is "???1", writing all 0 or all 1 will not affect the number of 1 substrings , you can specify to write 0. In this case, we can unify the situation at the beginning: all write 0.

If a question mark appears at the end: "1???", just write all 1 .
If the end is "0???", write all 0. That is, write whatever is at the beginning .

So all of the above can be boiled down to the following approach:

If it starts with ? , just change it to 0, the rest? All are consistent with the previous character. (You can verify it yourself according to the above classification discussion)

3. Code

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;

void solve()
{
    
    
	string s;
	cin >> s;
	if(s[0] == '?')
		s[0] = '0';
	for(int i = 0; i < s.size() - 1; i ++)
		if(s[i + 1] == '?')
			s[i + 1] = s[i];
	cout << s << endl;	
}

signed main()
{
    
    
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--)
		solve();
}

D. Bracket Coloring

D. Bracket Coloring

1. Problem

Given a bracket sequence, if the bracket sequence can be matched, for example: "()()", "(()())", "((()))", or reversed, it can be matched For example: ")(", "))((", it is called a beautiful bracket sequence.

Now give us a random bracket sequence, we need to color this bracket sequence, the brackets of the same color need to form a beautiful bracket sequence.

Now we need to output the minimum required color and coloring strategy. If the sequence of beautiful brackets cannot be formed no matter how you color it, output -1.

2. Analysis

Because the left and right brackets need to be matched one by one, if the number of left brackets is not equal to the number of right brackets, it is impossible to construct an answer and output -1 directly.

If the number of left brackets is equal to the number of right brackets, it must be constructed. why?

For any one left and right brackets, ")(", "()", are beautiful, so in the worst case, if we color each pair of brackets, there will be n 2 \frac{ n }{2}2nbeautiful brackets. So there must be a solution.

After considering whether there is a solution, we next consider how to construct the optimal solution.

Here is a conclusion first, and then prove that the number of colors is either 1 or 2.

The case of 1 is simple, if the input bracket sequence is beautiful in itself, it only needs to be dyed 1 color.

Next, look at the situation of two colors:
insert image description here
if it is the situation in the picture above, there are at least two colors, which is understandable.
insert image description here
If it is the case of the left picture, you can unify the red brackets at the back into the blue brackets at the front. The rest of the situation is the same.

The next problem is the coloring problem.

For the problem of matching brackets, stacks are usually used to solve them. We put the first parenthesis on the stack, if the same parenthesis as the first parenthesis appears, put it on the stack, if there is a matching parenthesis, take a parenthesis from the top of the stack to match it, and then delete the top of the stack .

If you encounter a parenthesis that can match the parentheses in the stack, but the stack is empty, it needs to be painted another color. The remaining parentheses in the final stack also need to be painted in another color.

3. Code

#include<bits/stdc++.h>
#define endl '\n'
using namespace std;

void solve()
{
    
    
	int n; 
	string s;
	cin >> n >> s;
	int nums = 0;
	for(int i = 0; i < n; i ++)
		if(s[i] == '(')
			nums ++;
	if(2 * nums != n)
	{
    
    
		cout << -1 << endl;
		return;
	}
	string str = "";
	for(int i = n - 1; i >=0; i --)
		str.push_back(s[i]);

	vector<int>ans(n, 0);
	stack<pair<char,int>>stk1;
	for(int i = 0; i < n; i ++)
	{
    
    
		if(s[i] == s[0])
			stk1.push({
    
    s[i], i});
		else
		{
    
    
			if(stk1.empty())
				ans[i] = 2;
			else
			{
    
    
				auto t = stk1.top();
				stk1.pop();
				ans[t.second] = 1;
				ans[i] = 1;
			}
		}
	}
	while(stk1.size())
	{
    
    
		auto t = stk1.top();
		stk1.pop();
		ans[t.second] = 2;
	}
	int x = 0;
	
	for(int i = 0; i < n; i ++)
		x += ans[i];

	if(x == n || x == 2 * n)
	{
    
    
		cout << 1 << endl;
		for(int i = 0; i < n; i ++)
			cout << 1 << " ";
		cout << endl;
		return;			
	}
	
	cout << 2 << endl;
	for(auto x : ans)
		cout << x << " ";
	cout << endl;

}

signed main()
{
    
    
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--)
	solve();
}

E. Playoff Fixing

E. Playoff Fixing

1. Problem

2. Analysis

3. Code

F. Editorial for Two

F. Editorial for Two

1. Problem

Given a nnn andkkk , and a lengthnnn array. now fromnnAmong n numbers, pick outkkK numbers are called subsequences. Then divide this subsequence into two parts, denoted as subsequence 1 and subsequence 2. Then both subsequence 1 and subsequence 2 have a corresponding sum. These two sums can be compared to a maximum value. Now what we want isthe minimum value of the maximum value.

2. Analysis

Here is a very common routine. When the question asks us to find the minimum value of the maximum value or the maximum value of the minimum value, we usually use dichotomy to solve it.

We divide the final answer here.

For two points, the difficulty lies in check checkThe writing of c h ec k function.

In this question, check checkThe function of c h ec k function is to judge mid midin the process of dichotomyIs the mid value reasonable.

insert image description here
Then this picks out at most k 1 k1The process of k 1 numbers usesrepentance andgreed. The idea of ​​repentance and greed is when the sum of the selected numbers is less thanmid midWhen it is mid , choose as many numbers as possible, when it is greater thanmid midWhen mid , delete the maximum value in the selected number, the purpose is to leave more space to select more numbers, and this process of selecting the maximum value can be optimized with a large root heap.

In addition, the location of the prefix and suffix division in the figure is uncertain, so we need to enumerate all the division locations to find a feasible solution.

Therefore, we can first preprocess the most selected numbers k 1 , k 2 k1,k2 among all prefixes and suffixes by using repentance and greed.k 1 ,k 2 . Then enumerate the division positions and judge whether there is a group ofk 1 + k 2 ≥ k k1+k2 \geq kk 1+k2 _k

Recovery: O ( log ( sum ) ∗ ( nlogn + n ) ) = O ( log ( sum ) n logn ) O(log(sum)*(nlogn+n))=O(log(sum)\ n\ logn)O(log(sum)(nlogn+n))=O(log(sum) n logn)

3. Code

#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;


bool check(int maxv, int n, vector<int>a, int k)
{
    
    
	vector<int>f(n + 1, 0), g(n + 1, 0);
	priority_queue<int>q, qq;
	int sum = 0;
	for(int i = 0; i < n; i ++)
	{
    
    
		if(sum + a[i] <= maxv)
		{
    
    
			sum += a[i];
			q.push(a[i]);
			f[i + 1] = f[i] + 1;
		}
		else
		{
    
    
			q.push(a[i]);
			sum += a[i];
			sum -= q.top();
			q.pop();
			f[i + 1] = f[i];
		}
	}
	sum = 0;
	reverse(a.begin(), a.end());
	for(int i = 0; i < n; i ++)
	{
    
    
		if(sum + a[i] <= maxv)
		{
    
    
			sum += a[i];
			qq.push(a[i]);
			g[i + 1] = g[i] + 1;
		}
		else
		{
    
    
			sum += a[i];
			qq.push(a[i]);
			sum -= qq.top();
			qq.pop();
			g[i + 1] = g[i]; 
		}
	}

	for(int i = 1; i <= n; i ++ )
	{
    
    
		if(f[i] + g[n - i] >= k)
			return true;			
	}
	return false;

}

void solve()
{
    
    
	int n, k;
	cin >> n >> k;
	vector<int>a(n);
	int sum = 0;
	for(int i = 0; i < n; i ++)
	{
    
    
		cin >> a[i];
		sum += a[i];
	}
	int l = 0, r = sum;
	while(l < r)
	{
    
    
		int mid = l + r >> 1;
		if(check(mid, n, a, k))
			r = mid;
		else
			l = mid + 1;
	}
	cout << l << endl;
}

signed main()
{
    
    
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	int t;
	cin >> t;
	while(t--)
	solve();
}

Guess you like

Origin blog.csdn.net/weixin_72060925/article/details/131020674