# Weekly portal

I came to work in the company. I had a week's competition in my spare time. I asked three questions. I'm very satisfied. Ha ha ha. # 2011. Variable value after operation

Time complexity: O ( n ) O(n) O(n)

I've worked out a simple problem. The cumulative sum can be calculated according to the middle symbol of each operation.

class Solution {
public:
int finalValueAfterOperations(vector<string>& operations) {
int anw = 0;
for (const auto &s : operations) {
anw += (s == '+' ? 1 : -1);
}
return anw;
}
};


# 2012. Sum of array values

Idea: pretreatment

Time complexity: O ( n ) O(n) O(n)

With one-dimensional array s u f suf suf， s u f i suf_i sufi + n u m s i nums_i numsi is the minimum value in the suffix starting from.

You can enumerate from large to small i i i， O ( n ) O(n) O(n) pretreatment of all s u f i suf_i sufi​:
s u f i = m i n ( n u m s i , s u f i + 1 ) suf_i = min(nums_i, suf_{i+1}) sufi​=min(numsi​,sufi+1​)

Similarly, there is a one-dimensional array p r e pre pre， p r e i pre_i prei ， denotes n u m s i nums_i numsi is the maximum value in the prefix of the end point. Enumeration from small to large i i i， O ( n ) O(n) O(n) pretreatment of all p r e i pre_i prei​:
p r e i = m a x ( n u m s i , p r e i − 1 ) pre_i = max(nums_i, pre_{i-1}) prei​=max(numsi​,prei−1​)

At this point, the beauty value of each location can be O ( 1 ) O(1) The of O(1) is obtained:

• If p r e i − 1 < n u m s i < s u f i + 1 pre_{i-1} \lt nums_i \lt suf_{i+1} If prei − 1 < numsi < Sufi + 1, the beauty value is 2.
• If the above conditions are not met, and n u m s i − 1 ≤ n u m s i < n u m s i + 1 nums_{i-1} \le nums_i \lt nums_{i+1} Numsi − 1 ≤ numsi < numsi + 1, then the beauty value is 1.
• Other cases are 0.
class Solution {
public:
int sumOfBeauties(vector<int>& nums) {
vector<int> suf(nums.size(), nums.back());
for (int i = nums.size()-2; i >= 0; i--) {
suf[i] = min(suf[i+1], nums[i]);
}
vector<int> pre(nums.size(), nums);
for (int i = 1; i < nums.size(); i++) {
pre[i] = max(pre[i-1], nums[i]);
}
int sum = 0;
for (int i = 1; i <= nums.size()-2; i++) {
if (pre[i-1] < nums[i] && nums[i] < suf[i+1]) {
sum += 2;
} else if (nums[i-1] < nums[i] && nums[i] < nums[i+1]) {
sum += 1;
}
}
return sum;
}
};


# 2013. Test results

Idea: hash, diagonal

Time complexity: O ( a d d ∗ c o u n t ) O(add*count) O(add∗count)

There is a container m a r k mark mark, used to record the coordinates as ( x , y ) (x,y) The number of occurrences of the point of (x,y).

For each a d d ( x , y ) add(x,y) add(x,y) operation, just execute m a r k ( x , y ) + + mark(x,y)\mathrel{+}\mathrel{+} mark(x,y)++.

For each c o u n t ( x , y ) count(x,y) count(x,y) operation, you can enumerate all the coordinates that have occurred ( x 0 , y 0 ) (x_0,y_0) (x0, y0) to judge whether they can form the diagonal of a square, which meets the following two requirements:

• a b s ( x − x 0 ) = a b s ( y − y 0 ) abs(x-x_0) = abs(y-y_0) abs(x−x0​)=abs(y−y0​)
• x ≠ x 0 x \ne x_0 x​=x0​， y ≠ y 0 y \ne y_0 y​=y0​

If the above requirements are met, the coordinates of the other two points of the square can be calculated:

• x 1 = x , y 1 = y 0 x_1 = x, y_1 = y_0 x1​=x,y1​=y0​
• x 2 = x 0 , y 2 = y x_2 = x_0, y_2 = y x2​=x0​,y2​=y

When you get the four coordinates, from m a r k mark Found in mark ( x 0 , y 0 ) (x_0,y_0) (x0​,y0​)， ( x 1 , y 1 ) (x_1,y_1) (x1​,y1​)， ( x 2 , y 2 ) (x_2,y_2) (x2, y2) the number of points on the three coordinates is recorded as c 0 , c 1 , c 2 c_0,c_1,c_2 c0​,c1​,c2​.

accumulation c 0 ∗ c 1 ∗ c 2 c_0*c_1*c_2 c0 * c1 * c2 is this time c o u n t ( x , y ) count(x,y) The answer to the count(x,y) operation.

class DetectSquares {
public:
// Define the container mark, where key is the coordinate and value is the number of occurrences.
// The first 32 bits of the key store x and the last 32 bits store y. In this way, there is no need to define hash and operator = =
unordered_map<uint64_t, int> mark;

DetectSquares() {
}

// Number of occurrences of update point
mark[uint64_t(point)<<32|point]++;
}

int count(const vector<int> &point) {
int x = point, y = point;
int anw = 0; // anw is used to store the answers of this query

// Enumerate all occurrences
for (const auto &p : mark) {
int x0 = (p.first>>32), y0 = p.first&0xffff;
// Judge that (x,y) and (x0,y0) can form the diagonal of a square.
if (x == x0 || y == y0) continue;
if (abs(x-x0) != abs(y-y0)) continue;

int x1 = x, y1 = y0;
int x2 = x0, y2 = y;
auto it1 = mark.find(uint64_t(x1)<<32|y1);
auto it2 = mark.find(uint64_t(x2)<<32|y2);
// Judge whether the other two points exist.
if (it1 != mark.end() && it2 != mark.end()) {
// Cumulative c0*c1*c2
anw += it1->second * it2->second * p.second;
}
}
return anw;
}
};

/**
* Your DetectSquares object will be instantiated and called as such:
* DetectSquares* obj = new DetectSquares();
* int param_2 = obj->count(point);
*/


# 2014. Longest subsequence repeated K times

Idea: Full Permutation, enumerating subsets, pruning

Time complexity: O ( n ∗ r ! ∗ 2 r ) O(n*r!*2^r) O(n∗r!∗2r). n n n is the length of the input string, r r r is the upper limit of the length of the answer.

First, we will appear more than once k k Find the character of k and record it as a set r e m a i n remain remain.

Every occurrence of the same character k k Join k times r e m a i n remain remain once, so as to facilitate the processing of repeated characters in the sequence.

Consider the length of the input string n ∈ [ 2 , k ∗ 8 ) n\in[2,k*8) n ∈ [2,k * 8). Therefore, r e m a i n remain There must be no more than 7 elements in remain.

Violence enumeration r e m a i n remain All permutations of all subsets of remain p p p. About 7 ! ∗ 2 7 7!*2^7 7! * 27 kinds. For each kind p p p check that it is s s The number of occurrences in s. the overall time complexity is O ( n ∗ r ! ∗ 2 r ) O(n*r!*2^r) O(n * r! * 2r). Approx 1 e 9 1e9 1e9, it must timeout. Here is a pruning strategy.

Consider permutation p p p in s s The number of occurrences in s is less than k k k. Then all p p The permutations with p as the prefix can not be candidate answers, so there is no need to enumerate these permutations.

Consider appearing k k k times, length r ∈ [ 1 , 7 ] r\in[1,7] The subsequences of r ∈ [1,7] are C 7 r ∗ 2 r C_7^r*2^r C7r * 2r species, about 3 r 3^r 3r species. Therefore, after adding pruning, it will only be processed 3 r 3^r 3r effective permutations. Other permutations will be filtered because a short prefix does not appear. Therefore, the lower limit of time complexity is reduced to O ( 3 r ∗ n ) O(3^r*n) O(3r * n), as for the upper limit, I didn't think how to estimate it 🙁. . .

class Solution {
public:
int k_ = 0;
bool check(const std::string &input, const std::string &tmp) {
int i = 0, j = 0, k =0;
for (; j < input.size(); j++) {
if (tmp[i] == input[j]) {
i++;
if (i == tmp.size()) {
i = 0;
k++;
}
}
}
return k >= k_;
}
/*
* part String constructed during recursion
* pos It's time to deal with remain[pos]
* remain Preprocessed character set
* input Input string s
* anw Used to store answers
*/
void cst(std::string part, int pos, const std::string &remain, const std::string &input, std::string &anw) {
// Recursive boundary
if (pos == remain.size()) { return; }

// If all the remaining characters are added to part and its length is still less than anw, there is no need to deal with it.
if (part.size() + remain.size()-pos < anw.size()) { return; }

// Enter the current character into part
{
auto tmp = part;
tmp += remain[pos];
do {
// Check whether the characters in tmp exceed k
if (check(input, tmp)) {
if (tmp.size() > anw.size() || (tmp.size() == anw.size() && tmp > anw)) {
anw = tmp;
}
// tmp appears k times. Try adding other characters.
cst(tmp, pos+1, remain, input, anw);
}
} while(std::next_permutation(tmp.begin(), tmp.end()));
}

// The current character is not added to part.
{
cst(part, pos+1, remain, input, anw);
}
}

string longestSubsequenceRepeatedK(string s, int k) {
k_ = k; // Copy k to the member function for easy processing
std::string remain; // A character set that appears at least k times
unordered_map<char, int> count; // Used to count the number of occurrences of each character.

// Statistical times
for (auto c : s) {
count[c]++;
}

// Initialize retain. Add retain once every k occurrences of the character.
for (auto &p : count) {
while (p.second >= k) {
p.second -= k;
remain += p.first;
}
}
// Sorting is to use std::next_permutation
sort(remain.begin(), remain.end());

std::string anw; // Used to store answers
cst("", 0, remain, s, anw); // Enumerate all permutations and find answers

return anw;
}
};


Posted on Mon, 20 Sep 2021 15:46:55 -0400 by devang23