Advanced algorithm exercises for programmers (54)

Time:2022-6-19

text

Topic 1

Title Link
Main idea:
Give n integers and a number d;
It is required to remove the minimum number so that the difference between the maximum and minimum values of the remaining numbers is not greater than D;

input data:
n and d (1 ≤ n ≤ 100, 0 ≤ d ≤ 100)
(1 ≤ x[i] ≤ 100)

Examples
input
3 1
2 1 4
output
1

Topic analysis:
Method 1:
Greed. Suppose the final result is that the interval is [left, right], then all numbers less than left and greater than right should be discarded.
First, sort the array. Assuming that the number a[i] is left, you can quickly calculate the number that should be discarded by binary search right=a[i]+d.

Method 2:
Violence. Sort first, enumerate the reserved data range [left, right], and calculate whether the difference between the maximum and minimum values is less than D.

Method 3:
Scanline. Sort first, scan from left to right, and keep an interval where the difference between the maximum and minimum values is less than D; If the interval is not satisfied, the element is discarded from the left of the interval.

int a[N];

int main(int argc, const char * argv[]) {
    // insert code here...
    int n, d;
    cin >> n >> d;
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
    }
    
    sort(a, a + n);
    int ans = n;
    for (int i = 0; i < n; ++i) {
        int right = upper_bound(a, a + n, a[i] + d) - a;
        ans = min(ans, i + n - right);
    }
    cout << ans << endl;
    
    
    return 0;
}

Topic 2

Title Link
Main idea:
Give four integers n, K, a, B;
Now you need to change the number n to the number 1. There are two operations at a time:
1. N=n-1, the price is a;
2. N=n/k, the cost is B; (the requirement is that n can be divided by K)
Find the minimum cost.

input data:
Four lines of integers, representing n, K, a, B respectively (1  ≤  n, K, a, B  ≤  2 · 1e9)

Examples
input
9
2
3
1
output
6

Example explanation:
Subtract 1 from x (9 → 8) paying 3 coins.
Divide x by 2 (8 → 4) paying 1 coin.
Divide x by 2 (4 → 2) paying 1 coin.
Divide x by 2 (2 → 1) paying 1 coin.

Topic analysis:
The direct method is to judge the cost of each operation and select the lowest cost for operation until the number becomes 1.
However, because the number of n is large, if an extreme situation occurs, n-1 operations 1 may be performed, which makes the complexity too high.

To put it another way, operation 2 can only occur when n%k==0, so you only need to interpret the number n to become n/kWhether the operation cost of K is cost-effective.
Assume t=n/k
k. Then if it is not cost-effective to operate 2 on the number T, then all subsequent operations 2 are not cost-effective.

reflection:
The code is simple.

int main(int argc, const char * argv[]) {
    lld n, k, a, b;
    cin >> n >> k >> a >> b;
    lld ans = (n - 1) * a;
    while (n > 1) {
        lld t = n / k * k;
        if ((t - t / k) * a <= b) {
            break;
        }
        else {
            n = t / k;
            ans = ans - (t - t / k) * a + b;
        }
    }
    cout << ans << endl;
    return 0;
}

Topic 3

Title Link
Main idea:
Give a string STR of length N, which is composed of lowercase letters;
Now you need to spell a new string, which requires:
1. The length is k, all are lowercase letters, and all letters have appeared in str;
2. The dictionary order of the new string is greater than STR and as small as possible;

input data:
The first line N and K (1   K ≤   n,   K ≤   100   000)
Second line string str

Examples
input
3 3
abc
output
aca
Example explanation:
aaa, aab, aac, aba, abb, abc, aca, acb, …. All meet condition 1;
The lexicographic order is greater than ABC, and ACA is as small as possible;

Topic analysis:
The topic is divided into two situations:
1. K > N, you only need to fill the following characters with the smallest character in str (strnew STR);
2. K < = n, traverse from right to left to find a bit I, strnew[i]>str[i], and all subsequent characters are filled with the smallest character in str.

reflection:
You can also think in the way of analog addition. For example, the next string of ABC is abc+a=abd, and the D carry becomes ACA.

char str[N];
int vis[3333];

int main(int argc, const char * argv[]) {
    int n, k;
    cin >> n >> k;
    cin >> str;
    for (int i = 0; i < n; ++i) {
        vis[str[i]] = 1;
    }
    if (k > n) {
        cout << str;
        for (int i = 0; i < 26; ++i) {
            int index = 'a' + i;
            if (vis[index]) {
                for (int j = 0; j + n < k; ++j) {
                    putchar(index);
                }
                break;
            }
        }
        cout << endl;
    }
    else {
        for (int i = k - 1; i >= 0; --i) {
            int bigger = 0;
            for (int j = str[i] + 1; j < 'a' + 26; ++j) {
                if (vis[j]) {
                    bigger = j;
                    break;
                }
            }
            if (bigger) {
                str[i] = bigger;
                
                for (int j = 0; j < 26; ++j) {
                    int index = 'a' + j;
                    if (vis[index]) {
                        for (int t = i + 1; t < k; ++t) {
                            str[t] = index;
                        }
                        break;
                    }
                }
                break;
            }
        }
        str[k] = 0;
        cout << str << endl;
    }
    return 0;
}

Topic 4

Title Link
Main idea:
We use a string to describe a necklace. The string is composed of’o’and’ – ‘, O represents beads and – represents chains; (the first and last characters of the string are connected)
Now you can recombine the necklace, that is, rearrange the strings of’o” – ‘, and ask whether it meets the requirements:
The number of chains between beads is the same;

Input:
The first line: String STR, indicating the necklace; (note that there may be one bead, multiple beads and no beads)
Output:
Yes if the requirements can be met, no if the requirements cannot be met;

input data:

Examples
input
-o-o–
output
YES

Topic analysis:
First count the quantity x, y of – and O;
Classified discussion:
When y=0, it must be yes;
y!= 0, then when x%y==0, yes; Otherwise, it is no;

int main(int argc, const char * argv[]) {
    string str;
    cin >> str;
    int x = 0, y = 0;
    for (int i = 0; i < str.length(); ++i) {
        if (str[i] == '-') {
            ++x;
        }
        else {
            ++y;
        }
    }
    if (y == 0 || x % y == 0) {
        cout << "YES" << endl;
    }
    else {
        cout << "NO" << endl;
    }
    return 0;
}

Topic 5

Title Link
Main idea:
Xiaoming is taking an image algorithm course. The teacher asked him to implement an image filter algorithm. The process can be described as follows:
Give n numbers p[i], [0, 255] range, indicating color;
Divide the range [0, 255] into multiple intervals, such as [0, 4], [5, 9], [10, 14] The size of the interval shall not exceed K; (note that the intervals are required to be continuous, the number of intervals is not required, and the length of intervals is limited)
Then process the data. All the numbers in the interval [0, 4] can be represented by 0, which is the same as [5, 9]=5;
It is required that the dictionary order formed by all numbers after processing shall be the smallest.

Input:
The first line n, K (1 ≤ n ≤ 1E5, 1 ≤ K ≤ 256)
The second line p 1, P 2,…, P n (0 ≤ P I ≤ 255)

Output:
Process the N digits after the word.

Examples
input
4 3
2 14 3 4
output
0 12 3 3

Example explanation
Color 2 belongs to group [0, 2] = 0
color 14 = group [12, 14] = 12
color 3,4 = group [3, 5] = 3
So the final number is 0, 12, 3, 3

Topic analysis:
All numbers form the smallest lexicographic order, which means that the smaller the preceding number, the better.
When considering the i-th number, the data after i+1 can be ignored and the i-th number can be minimized as far as possible.
From this, we can get a greedy strategy:
By default [0, 255] do not assign an interval. For the ith number, its color value p[i], we start from p[i]-1 to find the unassigned interval. At this time, there are two situations:
1. If there is no assignment, then we can assign (p[i] – K + 1, p[i]) to an interval;
2. Find an allocated interval (x, y), and see whether the length of this interval can reach (x, p[i]). If so, enlarge the interval to (x, p[i]);
If the length is not enough, an interval is allocated from (y + 1, p[i]);
In this way, we can get a minimum dictionary order.

int main(int argc, const char * argv[]) {
    int n, k;
    cin >> n >> k;
    int cnt = 1;
    for (int index = 0; index < n; ++index) {
        int x;
        cin >> x;
        if (!color[x]) {
            int cur, ok = 0;
            for (cur = x - 1; cur >= 0 && cur + k > x; --cur) {
                if (color[cur]) {
                    int len = checkLen(cur);
                    if (len + (x - cur) <= k) {
                        ok = color[cur];
                    }
                    break;
                }
            }
            
            if (ok) {
                while (cur <= x) {
                    color[cur++] = ok;
                };
            }
            else {
                while (cur < x) {
                    ++cur;
                    color[cur] = cnt;
                }
                cnt++;
            }
        }
        cout << x - checkLen(x) + 1 << " ";
    }
    return 0;
}

summary

Topic 1: the topic is simple, but there are many methods;
Topic 2: greedy thinking, when the key nodes of decision-making can be divided;
Topic 3, simulated addition, the idea of using classification discussion is also very clear;
Topic 4: classified discussion. The ring is something that takes a lot of brain to simulate. You can draw pictures and think about it;
Topic 5, greedy, try to make the number in front smaller.