ACwing: algorithm basic course Chapter 1 floating point dichotomy, high precision, prefix sum, interval sum, interval merging, bit operation, double pointer algorithm, discretization template sorting

One. Floating point binary template sorting

1. step
one ⃣ When the accuracy is determined and the cycle condition is R-L > the accuracy
two ⃣ Calculate the middle value mid, which is always double Mid=(l+r)/2
three ⃣ If the condition is met, the right boundary will be reduced (for example, if the condition is that r is greater than the middle value, the left boundary will be returned finally)
four ⃣ ﹥ write the judgment condition satisfaction function

2. Code

bool check(double x) {/* ... */} // Check whether x satisfies a certain property

double bsearch_3(double l, double r)
{
    const double eps = 1e-6;   // eps indicates accuracy, which depends on the accuracy requirements of the subject
    while (r - l > eps)
    {
        double mid = (l + r) / 2;
        if (check(mid)) r = mid;
        else l = mid;
    }
    return l;
}

2, High precision addition

⚠️ Note that in the input and output of high-precision processing, the data should be read in the form of string, and then stored into the shaping array bit by bit. Note that - '0' should be subtracted to become integer data.

1. Steps:
one ⃣ Determine whether the first parameter is long and the second parameter is short. If not, return the transferred function
two ⃣ Set a stored variable C of the same type and a carry variable t
three ⃣ Start the cycle and add from bits. Note that the limit length of the cycle is the large integer with longer bits. In addition, add the carry t first, and then t is used to store the added value. Therefore, the number after t takes the modulus should be put into C, and then divide by 10 to calculate the carry into the next one

2. Code

// C = A + B, A >= 0, B >= 0
vector<int> add(vector<int> &A, vector<int> &B)
{
    if (A.size() < B.size()) return add(B, A);

    vector<int> C;
    int t = 0;
    for (int i = 0; i < A.size(); i ++ )
    {
        t += A[i];
        if (i < B.size()) t += B[i];//Don't forget!!!
        C.push_back(t % 10);
        t /= 10;
    }

    if (t) C.push_back(t);//The operation of this step can be combined with the loop like high-precision multiplication, because it is the same meaning and is used to deal with the last carry
    return C;
}

3, High precision subtraction

⚠️ Note that in the input and output of high-precision processing, the data should be read in the form of string, and then stored into the shaping array bit by bit. Note that - '0' should be subtracted to become integer data

1. Steps
one ⃣ Note that since the number of digits of the first parameter is relatively long in the template, this judgment can be made either in the template like the second point or when the main function calls high-precision subtraction
two ⃣ Set the storage subtracted variable C of the same type and set a carry variable t
three ⃣ ⒆ start the cycle. Note that the cycle is also added from bits, and then the length of the cycle is mainly the one with more bits. In addition, subtract t first, and then the T variable is used to store the result after subtracting each bit. Then, since t may be positive or negative, when it is positive, directly touch it and store it in the C variable, but if it is negative, add 10 and then take the module, Then the borrow is 1, so it can be summarized as: C. push_back ((T + 10)% 10); if (T < 0) t = 1; else t = 0;

2. Code

Insert code here// C = A - B, satisfying a > = B, a > = 0, b > = 0
vector<int> sub(vector<int> &A, vector<int> &B)
{
    vector<int> C;
    for (int i = 0, t = 0; i < A.size(); i ++ )
    {
        t = A[i] - t;
        if (i < B.size()) t -= B[i];
        C.push_back((t + 10) % 10);
        if (t < 0) t = 1;
        else t = 0;
    }

    while (C.size() > 1 && C.back() == 0) C.pop_back();
    return C;
}

4, High precision multiplication

⚠️ Note that in the input and output of high-precision processing, the data should be read in the form of string, and then stored into the shaping array bit by bit. Note that - '0' should be subtracted to become integer data

1. Steps

one ⃣ Note that since the number of digits of the first parameter in the template is relatively long, this judgment can either be judged in the template like the second point, or when the main function calls high-precision multiplication
two ⃣ Set a variable of the same type to store the multiplication result C and the carry result t
three ⃣ Then continue the cycle. Note that the number of times of this cycle should be dominated by long digits. In addition, it should be considered that the cycle should be carried out when the last bit has carry. Therefore, you can write an or as in this code. Of course, you can also judge whether T has carry as in the second and third points. In addition, t is used to store the result after each multiplication, Therefore, after t takes the remainder, Push it in, and / 10 is the next carry
four ⃣ ﹥ interval leading to zero

2. Code

// C = A * b, A >= 0, b >= 0
vector<int> mul(vector<int> &A, int b)
{
    vector<int> C;

    int t = 0;
    for (int i = 0; i < A.size() || t; i ++ )
    {
        if (i < A.size()) t += A[i] * b;
        C.push_back(t % 10);
        t /= 10;
    }

    while (C.size() > 1 && C.back() == 0) C.pop_back();

    return C;
}

5, High precision divided by low precision

⚠️ Note that since the previous templates are calculated from the position to the high position, it is better to divide from the high position. Therefore, the for loop starts from the last bit, that is, the highest position. When the stored result c is output, remember to reverse it first, because the previous templates store the results from the low position to the high position in C, so Rev is required erse

1. Steps

one ⃣ ⒈ it is the same, either judge the length in the function or in the calling function
two ⃣ Set the variable C storing the result and the result r after each bit
three ⃣ ⒆ start the for loop, and pay attention to the start and end of the for loop; in addition, pay attention to the remainder R, when entering the next calculation, the result of R = r*10+A[i]; then r divided by 10 becomes the quotient result, and the modulus divisor is the remainder of the next one
four ⃣ Remove leading zero

2. Code

//A/B=C...r,A>=0,b>0
vector<int> div(vector<int>&A,int b,int &r)
{
  vector<int> C;
  r=0;
  for(int i=A.size()-1;i>=0;i- -)
  {
    r=r*10+A[i];
    C.push_back(r/b);
    r%=b;
  }
  reverse(C.begin(),C.end());
  while(C.size()>1&&C.back()==0) C.pop_back();
  
  return C;
}

6, Prefix and

1. One dimensional prefix sum

We should pay attention to the problem of updating and inserting. We should look at the template Title ACWING 795 in detail
Look at the lecture notes

S[i] = a[1] + a[2] + ... a[i]
a[l] + ... + a[r] = S[r] - S[l - 1]

2. 2D prefix and

Mainly pay attention to the problem of updating and inserting. See the template Title ACWING 796 in detail

S[i, j] = The first i that 's ok j The sum of all elements in the upper left part of the column grid(x1, y1)Is the upper left corner,(x2, y2)The sum of the submatrix in the lower right corner is:
S[x2, y2] - S[x1 - 1, y2] - S[x2, y1 - 1] + S[x1 - 1, y1 - 1]

7, Differential array

1. One dimensional difference

Note that you should pay attention to the problem of updating and inserting. You should read the lecture notes and ACWING797 in detail

Give interval[l, r]Each number in the plus c: B[l] += c, B[r + 1] -= c

2. Two dimensional difference

The main thing is to pay attention to the problem of updating and inserting. You should look at the notes in detail. There is also topic 798

Give(x1, y1)Is the upper left corner,(x2, y2)Add to all elements in the submatrix in the lower right corner c: 
S[x1, y1] += c, S[x2 + 1, y1] -= c, S[x1, y2 + 1] -= c, S[x2 + 1, y2 + 1] += c

8, Bit operation

⚠️ Read the lecture notes in detail

seek n The first k Digit number: n >> k & 1
 return n Last 1: lowbit(n) = n & -n

9, Double pointer algorithm

⚠️ Read the lecture notes in detail

for (int i = 0, j = 0; i < n; i ++ )
{
    while (j < i && check(i, j)) j ++ ;

    // Logic of specific problems
}
Classification of frequently asked questions:
    (1) For a sequence, maintain an interval with two pointers
    (2) For two sequences, maintain a certain order, such as merging two ordered sequences in merge sort

10, Discretization

1. Steps
one ⃣ Store all values to be discretized, all
two ⃣ Sort all values
three ⃣ Remove the duplicate elements in all. At this time, the all array contains all the data stored, so there is no need to open a large array, and then the following table represents the data. Therefore, the next step is how to find the discretized position corresponding to x in all
four ⃣ ﹥ use dichotomy to find the position of x corresponding to all after discretization

2. Code

vector<int> alls; // Store all values to be discretized
sort(alls.begin(), alls.end()); // Sort all values
alls.erase(unique(alls.begin(), alls.end()), alls.end());   // Remove duplicate elements

// Find the discretized value corresponding to x
int find(int x) // Find the first position greater than or equal to x
{
    int l = 0, r = alls.size() - 1;
    while (l < r)
    {
        int mid = l + r >> 1;
        if (alls[mid] >= x) r = mid;
        else l = mid + 1;
    }
    return r + 1; // Map to 1, 2,... N
}

11, Interval merging

Merge the intervals of all existing intersections

1. Steps
one ⃣ Set the storage interval pair of vector variable
two ⃣ ﹥ sort the interval pairs according to the left end interval from small to large, and then set the left and right infinity boundaries
three ⃣ ﹥ traverse each interval, and then update it according to the lecture notes to find the merged interval

2. Code

// Merge all intersecting intervals
void merge(vector<PII> &segs)
{
    vector<PII> res;

    sort(segs.begin(), segs.end());

    int st = -2e9, ed = -2e9;
    for (auto seg : segs)
        if (ed < seg.first)
        {
            if (st != -2e9) res.push_back({st, ed});
            st = seg.first, ed = seg.second;
        }
        else ed = max(ed, seg.second);

    if (st != -2e9) res.push_back({st, ed});//This step is to add each merged interval, and the results are displayed there
    segs = res;
}

Tags: C Algorithm

Posted on Sat, 18 Sep 2021 02:26:59 -0400 by pesale86