What is the best method to solve this problem?

Here's the problem I'm trying to solve,

You are given a table with 2 rows and N columns. Each cell has an integer in it. Through this table denfiniruetsya follows: consider the sum of the two numbers in the column for each column; maximum obtained N numbers - an assessment. For example, for a table

July 1 June 2
1 2 3 4

max score (7 + 1, 1 + 2, 3 + 6, 2 + 4) = 9. The first row of the table is fixed and is specified as input. N possible paths for the second line are:

1; 2;:; N
2; 3;:; H; 1
3; 4;:; H; 1; 2
|
H; 1;:;; N 1

For example, in the above example, we look at each of the following options for the second row.

1 2 3 4
2 3 4 1
3 4 1 2
4 1 2 3

Your task - to find an estimate for each of the above options for the second row. In the example above, you would appreciate the following four tables,

July 1 June 2
1 2 3 4
7 1 6 2
2 3 4 1
July 1 June 2
3 4 1 2
July 1 June 2
4 1 2 3
and calculate estimates 9, 10, 10 and 11 respectively

Test data: N <= 200000
Time limit: 2 seconds

That's obvious method:

Maintain two arrays A, B, n times follow

  • adding each element of A [i] to B [i] and save variable max, which maintains the maximum value until now.
  • print max
  • iterate array B [i] and increase all the elements 1, if any element is equal to N, set it to one.

This method will have time O (n ^ 2), the outer loop is executed N times, and there are two internal cycles that are performed during every N times.

To reduce the time, we can find a maximal element M in the first row (in the linear scanning), and then remove the A [i] and B [i] whenever A [i] + N <= M + 1.
Because they will never be maximized.

But this method may work better in the average case, worst-case time is still O (N ^ 2).

To find the max in constant time, I also considered the use of the heap, each heap element has two attributes, their initial value and the value that you want to add. But this will require linear time to increase the value, which will be added for all elements of the heap for each of n cases.
So, the time is still O (N ^ 2)

I can not find a method that will allow to solve this problem faster than the N ^ 2 times, that is too slow, as the value of N can be very large.
Any help would be greatly appreciated.

+4
source share
2 answers

There is also the algorithm O (n). Using the same observations as in the previous answer:

Now consider what happens to the column sums when turning to the left of the second row (e.g., change it with 1,2, ..., N to 2,3, ..., N, 1) each column sum is incremented by 1, excluding one column sum, which is reduced by N-1.

Instead of changing all column sums, we can reduce one column sum by N, and then take the maximum column sum plus 1 to find the new maximum column sums. So we need to update only one column, but not all.

A column that displays the high, can only move left or returned to the column with a total maximum when we iterate possibility of a second line. Candidate columns are those that were a temporary maximum for maximum scans from left to right.

  • all amounts calculated for a first selection of the second row (1, 2, ..., N) and store them in an array.
  • find the maximum in this array in the scan mode from left to right and note the position of the maximum time.
  • in the right-left sum value is now reduced by decreasing N. If the process reaches the maximum column, check whether this number is less than the total maximum - N, in this case, the new maximum column is the overall maximum and it will remain there for the rest of the cycle. If the number is more than the previous high, determined in step 2, the maximum column will remain unchanged for the rest of the cycle. Otherwise, the previous high becomes the new maximum column.

Taking the example of an input 7,1,6,2, the algorithm works as follows: Step 1 calculates the sum of 8,3,9,6 Step 2 finds time maxima from left to right: 8 in column 1 and then 9 in column 3 Step 3 generates results passing through the array from right to left

8 3 9 6 -> output 9 + 0 = 9 8 3 9 2 -> output 9 + 1 = 10 8 3 5 2 -> current max col is decreased, previous max 8 is larger and becomes current output 8 + 2 = 10 8 -1 5 2 -> output 8 + 3 = 11 

Here is the algorithm in C:

 #include <stdio.h> int N; int A[200000]; int M[200000]; int main(){ int i,m,max,j,mval,mmax; scanf("%d",&N); for(i = 0;i < N; i++){ scanf("%d",&A[i]); A[i] = A[i]+i+1; } m = 0; max = 0; M[0] = 0; for(i = 1;i < N; i++){ if(A[i] > A[max]){ m++; M[m] = i; max = i; } } mval = A[max] - N; mmax = max; for(i = N-1,j = 0;i >=0;i --,j++){ printf("%d ", A[max]+j); A[i] = A[i] - N; if(i == max){ if (A[i] < mval) { max = mmax; } else if(m > 0 && A[i] < A[M[m-1]]){ max = M[m-1]; m--; } } } printf("\n"); return 0; } , mval, mmax; #include <stdio.h> int N; int A[200000]; int M[200000]; int main(){ int i,m,max,j,mval,mmax; scanf("%d",&N); for(i = 0;i < N; i++){ scanf("%d",&A[i]); A[i] = A[i]+i+1; } m = 0; max = 0; M[0] = 0; for(i = 1;i < N; i++){ if(A[i] > A[max]){ m++; M[m] = i; max = i; } } mval = A[max] - N; mmax = max; for(i = N-1,j = 0;i >=0;i --,j++){ printf("%d ", A[max]+j); A[i] = A[i] - N; if(i == max){ if (A[i] < mval) { max = mmax; } else if(m > 0 && A[i] < A[M[m-1]]){ max = M[m-1]; m--; } } } printf("\n"); return 0; } N); #include <stdio.h> int N; int A[200000]; int M[200000]; int main(){ int i,m,max,j,mval,mmax; scanf("%d",&N); for(i = 0;i < N; i++){ scanf("%d",&A[i]); A[i] = A[i]+i+1; } m = 0; max = 0; M[0] = 0; for(i = 1;i < N; i++){ if(A[i] > A[max]){ m++; M[m] = i; max = i; } } mval = A[max] - N; mmax = max; for(i = N-1,j = 0;i >=0;i --,j++){ printf("%d ", A[max]+j); A[i] = A[i] - N; if(i == max){ if (A[i] < mval) { max = mmax; } else if(m > 0 && A[i] < A[M[m-1]]){ max = M[m-1]; m--; } } } printf("\n"); return 0; } { #include <stdio.h> int N; int A[200000]; int M[200000]; int main(){ int i,m,max,j,mval,mmax; scanf("%d",&N); for(i = 0;i < N; i++){ scanf("%d",&A[i]); A[i] = A[i]+i+1; } m = 0; max = 0; M[0] = 0; for(i = 1;i < N; i++){ if(A[i] > A[max]){ m++; M[m] = i; max = i; } } mval = A[max] - N; mmax = max; for(i = N-1,j = 0;i >=0;i --,j++){ printf("%d ", A[max]+j); A[i] = A[i] - N; if(i == max){ if (A[i] < mval) { max = mmax; } else if(m > 0 && A[i] < A[M[m-1]]){ max = M[m-1]; m--; } } } printf("\n"); return 0; } A [i]); #include <stdio.h> int N; int A[200000]; int M[200000]; int main(){ int i,m,max,j,mval,mmax; scanf("%d",&N); for(i = 0;i < N; i++){ scanf("%d",&A[i]); A[i] = A[i]+i+1; } m = 0; max = 0; M[0] = 0; for(i = 1;i < N; i++){ if(A[i] > A[max]){ m++; M[m] = i; max = i; } } mval = A[max] - N; mmax = max; for(i = N-1,j = 0;i >=0;i --,j++){ printf("%d ", A[max]+j); A[i] = A[i] - N; if(i == max){ if (A[i] < mval) { max = mmax; } else if(m > 0 && A[i] < A[M[m-1]]){ max = M[m-1]; m--; } } } printf("\n"); return 0; } [max]) { #include <stdio.h> int N; int A[200000]; int M[200000]; int main(){ int i,m,max,j,mval,mmax; scanf("%d",&N); for(i = 0;i < N; i++){ scanf("%d",&A[i]); A[i] = A[i]+i+1; } m = 0; max = 0; M[0] = 0; for(i = 1;i < N; i++){ if(A[i] > A[max]){ m++; M[m] = i; max = i; } } mval = A[max] - N; mmax = max; for(i = N-1,j = 0;i >=0;i --,j++){ printf("%d ", A[max]+j); A[i] = A[i] - N; if(i == max){ if (A[i] < mval) { max = mmax; } else if(m > 0 && A[i] < A[M[m-1]]){ max = M[m-1]; m--; } } } printf("\n"); return 0; } ; #include <stdio.h> int N; int A[200000]; int M[200000]; int main(){ int i,m,max,j,mval,mmax; scanf("%d",&N); for(i = 0;i < N; i++){ scanf("%d",&A[i]); A[i] = A[i]+i+1; } m = 0; max = 0; M[0] = 0; for(i = 1;i < N; i++){ if(A[i] > A[max]){ m++; M[m] = i; max = i; } } mval = A[max] - N; mmax = max; for(i = N-1,j = 0;i >=0;i --,j++){ printf("%d ", A[max]+j); A[i] = A[i] - N; if(i == max){ if (A[i] < mval) { max = mmax; } else if(m > 0 && A[i] < A[M[m-1]]){ max = M[m-1]; m--; } } } printf("\n"); return 0; } [max] + j); #include <stdio.h> int N; int A[200000]; int M[200000]; int main(){ int i,m,max,j,mval,mmax; scanf("%d",&N); for(i = 0;i < N; i++){ scanf("%d",&A[i]); A[i] = A[i]+i+1; } m = 0; max = 0; M[0] = 0; for(i = 1;i < N; i++){ if(A[i] > A[max]){ m++; M[m] = i; max = i; } } mval = A[max] - N; mmax = max; for(i = N-1,j = 0;i >=0;i --,j++){ printf("%d ", A[max]+j); A[i] = A[i] - N; if(i == max){ if (A[i] < mval) { max = mmax; } else if(m > 0 && A[i] < A[M[m-1]]){ max = M[m-1]; m--; } } } printf("\n"); return 0; } ) { #include <stdio.h> int N; int A[200000]; int M[200000]; int main(){ int i,m,max,j,mval,mmax; scanf("%d",&N); for(i = 0;i < N; i++){ scanf("%d",&A[i]); A[i] = A[i]+i+1; } m = 0; max = 0; M[0] = 0; for(i = 1;i < N; i++){ if(A[i] > A[max]){ m++; M[m] = i; max = i; } } mval = A[max] - N; mmax = max; for(i = N-1,j = 0;i >=0;i --,j++){ printf("%d ", A[max]+j); A[i] = A[i] - N; if(i == max){ if (A[i] < mval) { max = mmax; } else if(m > 0 && A[i] < A[M[m-1]]){ max = M[m-1]; m--; } } } printf("\n"); return 0; } M [m- #include <stdio.h> int N; int A[200000]; int M[200000]; int main(){ int i,m,max,j,mval,mmax; scanf("%d",&N); for(i = 0;i < N; i++){ scanf("%d",&A[i]); A[i] = A[i]+i+1; } m = 0; max = 0; M[0] = 0; for(i = 1;i < N; i++){ if(A[i] > A[max]){ m++; M[m] = i; max = i; } } mval = A[max] - N; mmax = max; for(i = N-1,j = 0;i >=0;i --,j++){ printf("%d ", A[max]+j); A[i] = A[i] - N; if(i == max){ if (A[i] < mval) { max = mmax; } else if(m > 0 && A[i] < A[M[m-1]]){ max = M[m-1]; m--; } } } printf("\n"); return 0; } 
+5
source

Here is the solution O(n*logn) :

Suppose you have calculated the amount of all the columns for a specific location of the second row.

Now consider what happens to the column sums when turning to the left of the second row (e.g., change it with 1,2,...,N to 2,3,...,N,1 ) each column sum is incremented by 1, except a reduced the amount of N-1 column.

Instead of changing all amounts columns we can reduce the amount of a single column on the N, and then take the maximum amount of the column plus 1, to find the new maximum column sums. So we need to update only one column, but not all.

Thus, our algorithm will be:

  • Set the second line as 1,2, ..., N, and calculate the sum of each column. Put all of these amounts in the max-heap. The root of the pile will be the largest sum.

  • For i from 1 to N :

    • Reduce the heap node, the corresponding column Ni th to N .
    • The new maximum amount of the column - is the root of the heap plus i .

Each update heap takes O(logn) , which leads to the total time O(n*logn) .

+2
source

All Articles