# Codeforces Round #744 (Div. 3) problem solution complete A~G

## Codeforces Round #744 (Div. 3)

### A. Casimir's String Solitaire

#### meaning of the title

Give A string consisting only of characters' A ',' B 'and' C '. You can eliminate one' A 'and one' B 'at A time, or one' B 'and one' C 'at the same time. Ask whether all characters can be eliminated in the end.

#### thinking

It can be completely eliminated as long as the number of 'B' is equal to the sum of the numbers of 'A' and 'C'.

#### Time complexity

O ( 1 ) O(1) O(1)

#### AC code

ProblemLangVerdictTimeMemory
A - Casimir's String SolitaireGNU C++17Accepted15 ms3600 KB
#include <bits/stdc++.h>

using namespace std;

char s[55];

void solve() {
scanf("%s", s);
int n = strlen(s);		//Finding the number of characters in advance can reduce the complexity, but putting strlen into the loop can also pass this problem
int a = 0, b = 0;		//A the sum of the number of records' a 'and' C ', B the number of records' B'
for (int i = 0; i < n; ++i) {
if (s[i] == 'B') ++b;
else ++a;
}
if (a == b) printf("YES\n");
else printf("NO\n");
}

int main() {
//	freopen("in.txt", "r", stdin);
int t;
scanf("%d", &t);
while (t--) solve();
return 0;
}


### B. Shifting Sort

#### meaning of the title

Give a sequence of integers, one interval at a time [ l , r ] [l,r] [l,r], select a positive integer d d d. Parallel interval [ l , r ] [l,r] [l,r] cycle shift left d d d positions, at most n n After n operations, the sequence is ordered from small to large, and each operation needs to be output.

#### thinking

We can use the selective sorting method, select the minimum value, move it to the first position left, then select the minimum value in the remaining number, move it to the second position left, and so on. Note that if the minimum value is already in the first place, no operation is required.

#### Time complexity

O ( n 2 ) O(n^2) O(n2)

#### AC code

ProblemLangVerdictTimeMemory
B - Shifting SortGNU C++17Accepted31 ms3600 KB
#include <bits/stdc++.h>

using namespace std;

struct dt {
int l, r, d;

dt(int ll, int rr, int dd) {	//Constructor for empty_ back
l = ll, r = rr, d = dd;		//Instead of writing the constructor, replace it with push_back can also do it
}
};

int a[55], b[55];

void solve() {
int n;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
vector<dt> v;		//Record operation
for (int i = 1; i <= n; ++i) {
int mn = i;		//Record the location of the minimum value
for (int j = i + 1; j <= n; ++j) if (a[j] < a[mn]) mn = j;
if (mn == i) continue;	//The minimum value is exactly the first
int d = mn - i;
v.emplace_back(i, n, d);	//Record operation
for (int j = i; j <= n; ++j) {		//Simulate circular movement and update the array
if (j - d >= i) b[j - d] = a[j];
else b[n + 1 + j - d - i] = a[j];
}
for (int j = i; j <= n; ++j) a[j] = b[j];
}
printf("%d\n", v.size());
for (auto &i: v) printf("%d %d %d\n", i.l, i.r, i.d);
}

int main() {
//	freopen("in.txt", "r", stdin);
int t;
scanf("%d", &t);
while (t--) solve();
return 0;
}


### C. Ticks

#### meaning of the title

Give a n n n line m m The grid array of m columns defines the pattern "check": ∀ h ∈ [ 0 , d ] \forall h\in[0,d] ∀ h ∈ [0,d], coordinates ( i − h , j ± h ) (i-h,j\pm h) The squares of (i − h,j ± h) are blackened ( i , j ) (i,j) (i,j) is the center and the height is d d d "check". Ask whether a given grid array can be composed of several heights not less than k k k's "cross check" composition (different cross checks are allowed to overlap).

#### thinking

The center of existence is located in ( i , j ) (i,j) (i,j), height d d The necessary and sufficient conditions for "checking" of d are: ( i , j ) (i,j) (i,j) start, with at least d d d consecutive black squares. Similarly, the necessary and sufficient condition for a black grid to belong to a "check mark" is: from this position ( x , y ) (x,y) (x,y) start looking in the lower left and lower right directions, and you can find a position ( i , j ) (i,j) (i,j) so that there is a center located at ( i , j ) (i,j) (i,j), not less than x − i x-i "Check" of x − i. Therefore, it is only necessary to preprocess the longest number of continuous black grids in the upper left and right directions at each position, and then judge whether the conditions are met.

#### Time complexity

O ( n 3 ) O(n^3) O(n3)

#### AC code

ProblemLangVerdictTimeMemory
C - TicksGNU C++17Accepted31 ms3700 KB
#include <bits/stdc++.h>

using namespace std;

char s[20][20];
int a[20][20], b[20][20];		//Array a records the number of the longest continuous black squares at the top left, and array b records the number of black squares at the top right
int n, m, k;

bool check() {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (s[i][j] == '.') continue;	//Only the black squares are judged, and the white squares are directly ignored
bool ok = false;
int x, y, cnt;
x = i, y = j, cnt = 0;
while (x < n && y < m) {
if (a[x][y] >= max(k, cnt) && b[x][y] >= max(k, cnt)) {		//Upper left and upper right shall be met at the same time
ok = true;
break;
}
++cnt, ++x, ++y;
}
if (ok) continue;
x = i, y = j, cnt = 0;
while (x < n && y >= 0) {
if (a[x][y] >= max(k, cnt) && b[x][y] >= max(k, cnt)) {
ok = true;
break;
}
++cnt, ++x, --y;
}
if (!ok) return false;
}
}
return true;
}

void solve() {
scanf("%d%d%d", &n, &m, &k);
for (int i = 0; i < n; ++i) scanf("%s", s[i]);
memset(a, 0, sizeof a);
memset(b, 0, sizeof b);
for (int i = 0; i < n - 1; ++i)		//The number of continuous black lattices in the upper left direction is calculated by recursion in the lower right direction
for (int j = 0; j < m - 1; ++j)
if (s[i][j] == '*' && s[i + 1][j + 1] == '*') a[i + 1][j + 1] = a[i][j] + 1;
for (int i = 0; i < n - 1; ++i)		//Recursion to the lower left to find the number of continuous black lattices in the upper right direction
for (int j = m - 1; j > 0; --j)
if (s[i][j] == '*' && s[i + 1][j - 1] == '*') b[i + 1][j - 1] = b[i][j] + 1;
if (check()) printf("YES\n");
else printf("NO\n");
}

int main() {
//	freopen("in.txt", "r", stdin);
int t;
scanf("%d", &t);
while (t--) {
solve();
}
return 0;
}


### D. Productive Meeting

#### meaning of the title

At the meeting n n n individuals, No i i i people are willing to discuss at most a i a_i ai # times, any two people can discuss any number of times. The topic requires to find out the maximum number of discussions and output the discussion scheme.

#### thinking

Greedily find out the two people who are willing to discuss the most times, make them discuss once, and repeat this operation until no more two people are willing to discuss. In order to find the most frequent people, just use the heap (priority queue).

#### Time complexity

O ( n l o g 2 n ) O(nlog_2n) O(nlog2​n)

#### AC code

ProblemLangVerdictTimeMemory
D - Productive MeetingGNU C++17Accepted109 ms7300 KB
#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> pii;

void solve() {
int n;
scanf("%d", &n);
priority_queue<pii> q;		//Large top reactor
for (int i = 1; i <= n; ++i) {
int p;
scanf("%d", &p);
if (p) q.emplace(p, i);
}
vector<pii> v;		//Used to record the process
while (q.size() > 1) {
pii a = q.top();		//Two elements at the top of the heap were found
q.pop();
pii b = q.top();
q.pop();
v.emplace_back(a.second, b.second);		//Record a discussion
--a.first, --b.first;		//Reduce the number of discussions
if (a.first) q.push(a);
if (b.first) q.push(b);
}
printf("%d\n", v.size());
for (auto &i: v) printf("%d %d\n", i.first, i.second);
}

int main() {
//	freopen("in.txt", "r", stdin);
int t;
scanf("%d", &t);
while (t--) solve();
return 0;
}


### E1. Permutation Minimization by Deque

#### meaning of the title

Give a sequence and join an empty double ended queue in turn. You can optionally join from the beginning or the end. Find the result of the smallest possible dictionary order. Please understand the meaning of dictionary order by yourself.

#### thinking

Adopt the greedy strategy. If the newly added element is greater than the team head, it will be added at the end of the team, otherwise it will be added at the head of the team. Simulation results can be obtained.

#### Time complexity

O ( n ) O(n) O(n)

#### AC code

ProblemLangVerdictTimeMemory
E1 - Permutation Minimization by DequeGNU C++17Accepted109 ms4700 KB
#include <bits/stdc++.h>

using namespace std;

void solve() {
int n;
scanf("%d", &n);
deque<int> q;		//Double ended queue
int p;
scanf("%d", &p);
q.push_back(p);		//Add the first element directly
for (int i = 1; i < n; ++i) {
scanf("%d", &p);		//Add the remaining elements after comparison
if (p > q.front()) q.push_back(p);
else q.push_front(p);
}
for (int i: q) printf("%d ", i);	//output
printf("\n");
}

int main() {
//	freopen("in.txt", "r", stdin);
int t;
scanf("%d", &t);
while (t--) solve();
return 0;
}


### E2. Array Optimization by Deque

#### meaning of the title

Give a sequence and join an empty double ended queue in turn. You can optionally join from the beginning or the end. Find the least possible reverse order pairs. Please understand the meaning of reverse order pairs.

#### thinking

Consider the last element. Whether it is at the head of the team or at the end of the team, the number of reverse pairs generated is independent of the order of other elements. Therefore, greedily select the scheme with less reverse pairs. Then, the penultimate element is processed in exactly the same way as the last element. Note: when processing the penultimate element, it is not necessary to consider whether it will have an inverse pair with the last element, because it has been calculated during the calculation of the last element. Repeat this operation to process all elements. To calculate the number of pairs in reverse order, you can use a tree array. The data range of this problem is large and needs to be discretized first.

#### Time complexity

O ( n l o g 2 n ) O(nlog_2n) O(nlog2​n)

#### AC code

ProblemLangVerdictTimeMemory
E2 - Array Optimization by DequeGNU C++17Accepted280 ms11700 KB
#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 5;

int a[N], d[N], cnt;			//cnt records the quantity after discretization

int lowbit(int x) {
return x & -x;
}

void upd(int x, int k) {		//Single point modification of tree array
for (int i = x; i <= cnt; i += lowbit(i)) d[i] += k;
}

int sum(int x) {				//Tree array interval summation
int r = 0;
for (int i = x; i > 0; i -= lowbit(i)) r += d[i];
return r;
}

void solve() {
int n;
scanf("%d", &n);
map<int, int> m;			//For discretization
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
m[a[i]];
}
cnt = 0;
for (auto &i: m) i.second = ++cnt;
for (int i = 1; i <= n; ++i) a[i] = m[a[i]], upd(a[i], 1);	//Discretize and add 1 to this position in the tree array
long long ans = 0;
for (int i = n; i >= 1; --i) {
int l = sum(a[i] - 1), r = sum(cnt) - sum(a[i]);
if (l > r) ans += r, upd(a[i], -1);
else ans += l, upd(a[i], -1);
}
printf("%lld\n", ans);
memset(d, 0, (cnt + 5) << 2);		//Remember to empty the tree array
}

int main() {
//	freopen("in.txt", "r", stdin);
int t;
scanf("%d", &t);
while (t--) solve();
return 0;
}


### F. Array Stabilization (AND version)

#### meaning of the title

There is an array of 0 and 1 only a a a. Memory array a a a cycle shift left d d The sequence obtained after d positions is a → d a^{\to d} a → d, right now a a Each element of a a i a_i ai, replace with a i & a i → d a_i\&a_i^{\to d} ai & ai → d, called one operation. The operation is repeated until the whole sequence does not change, which is called steady state. It is required to judge whether 1 still exists in the stable state. If so, output - 1. Otherwise, calculate the operands required from the initial state to the stable state.

#### thinking

if and only if a i = a ( i − d + n ) % n = 1 a_i=a_{(i-d+n)\%n}=1 When ai = a(i − d+n)%n = 1, after one operation, a i a_i ai is still 1. So we just need violence to simulate jumping d d For the operation of d positions, find the longest continuous number of 1, and then you can get the answer. In this process, there is a property: order k = g c d ( n , d ) k=gcd(n,d) k=gcd(n,d) (gcd represents the greatest common divisor), then we can find k k k independent cycles, and the length of each cycle is n k \frac{n}{k} kn​. So when the number of consecutive ones reaches n k \frac{n}{k} When kn ， it indicates that 1 will exist no matter how many operations.

Friendly reminder 1: attention d d d data range, d = n d=n d=n is possible, which will lead to some writing timeout, which can pass the special judgment d = n d=n d=n solution.

Friendly reminder 2: the above-mentioned "properties" can be rigorously expressed and proved by the methods of groups and subgroups in discrete mathematics, and will not be explained here.

Friendly reminder 3: the data range of this question is very large. The solution seems violent, but in fact it is not complex. You can write it at ease.

#### Time complexity

O ( n ) O(n) O(n)

#### AC code

ProblemLangVerdictTimeMemory
F - Array Stabilization (AND version)GNU C++17Accepted249 ms11500 KB
#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;

int a[N], b[N];

void solve() {
int n, d;
scanf("%d%d", &n, &d);
memset(b, 0, (n + 5) << 2);		//Don't use all memset s. It's easy to time out
for (int i = 0; i < n; ++i) scanf("%d", &a[i]);
if (d == n) {			//Special judgment d=n
for (int i = 0; i < n; ++i) {
if (a[i]) {
printf("-1\n");
return;
}
}
printf("0\n");
return;
}
int k = __gcd(n, d), lim = n / k, ans = 0;
for (int i = 0; i < k; ++i) {
int pos = i;
for (int j = 0; j < 2 * lim; ++j) {		//Two rounds of simulation shall be carried out to avoid errors due to the connection between the head and the tail
if (a[(pos + d) % n]) b[(pos + d) % n] = b[pos % n] + 1;
if (b[(pos + d) % n] >= lim) {		//There must be a case of 1
printf("-1\n");
return;
}
pos = (pos + d) % n;
}
}
for (int i = 0; i < n; ++i) ans = max(ans, b[i]);
printf("%d\n", ans);
}

int main() {
//	freopen("in.txt", "r", stdin);
int t;
scanf("%d", &t);
while (t--) solve();
return 0;
}


### G. Minimal Coverage

#### meaning of the title

There are several line segments on a one-dimensional number axis, and the starting point of the first line segment is at 0. Given the length of the line segment, the adjacent line segments must be connected from end to end, but the direction must not be the same. Find the minimum total coverage length after these line segments are connected.

The meaning of the question is difficult to understand. For example, the length of the line segment is [ 7 , 8 , 6 ] [7,8,6] [7,8,6], the first line segment covers the interval [ 0 , 7 ] [0,7] [0,7], the second line segment covers the interval [ − 1 , 7 ] [-1,7] [− 1,7], the third line segment covers the interval [ − 1 , 5 ] [-1,5] [− 1,5], then the total coverage is [ − 1 , 7 ] [-1,7] [− 1,7], length 8.

#### thinking

The general idea adopts the dichotomy strategy to dichotomy the answer, and the upper bound of dichotomy is 2 ⋅ m a x   a i 2\cdot max\ a_i 2⋅max   ai​. Value for each attempt m i d mid mid, we can record the possible position of the tail end of the processed line segment, and update the possible position every time a new line segment is added. Because this position cannot be more than m i d mid mid units, we need to delete out of range locations (we can update without adding).

Method optimization 1: using bitset in STL container to optimize the operation of updating possible locations can greatly improve efficiency and reduce the amount of code (using left shift, right shift, and, or operation).

Method optimization 2: there may be negative numbers at the end of the line segment, so it will be troublesome to directly use the array or bitset (you need to add an appropriate number to convert the negative number into a positive number). In fact, it doesn't matter where the starting point of the first line segment is (that is, it doesn't have to start from 0), so you might as well set the initial state to 0 m i d mid mid 1. This method requires a certain understanding ability, and can not be used if it cannot be understood. The code provided below adopts this method.

#### Time complexity

O ( n l o g 2 n ⋅ m a x   a i ) O(nlog_2n\cdot max\ a_i) O(nlog2​n⋅max ai​)

#### AC code

ProblemLangVerdictTimeMemory
G - Minimal CoverageGNU C++17Accepted46 ms3700 KB
#include <bits/stdc++.h>

using namespace std;

int a[10005];
int n;

bool check(int x) {
bitset<2005> b, c;
for (int i = 0; i <= x; ++i) b[i] = c[i] = true;				//Moving left means the direction of the line segment is negative, and moving right means positive
for (int i = 0; i < n; ++i) b = (b << a[i] | b >> a[i]) & c;	//&The purpose of C is to remove out of range positions
return b.any();
}

void solve() {
scanf("%d", &n);
for (int i = 0; i < n; ++i) scanf("%d", &a[i]);
int l = 0, r = 2000, ans;			//Two point answer
while (l <= r) {
int mid = (l + r) >> 1;
if (check(mid)) ans = mid, r = mid - 1;
else l = mid + 1;
}
printf("%d\n", ans);
}

int main() {
//	freopen("in.txt", "r", stdin);
int t;
scanf("%d", &t);
while (t--) solve();
return 0;
}


Posted on Thu, 14 Oct 2021 15:48:13 -0400 by m00gzilla