2020 Niuke Summer Multi-school Training Camp (Second Session) F Fake Maxpooling

2020/7/14
Hey, you don't know the taste of +17 . The problem card constructs the lcm matrix, and the complexity of the violent matrix is ​​nmlogn. This is the logn that is stuck. A special judgment was added in the game and the complexity was reduced by half. The positive solution is the sieve method given in the problem solution to construct the lcm matrix

for (int i = 1; i <= n; i ++)
	for (int j = 1; j <= m; j ++)
		if (!Gcd[i][j])
		for (int k = 1; k * i <= n && k * j <= m; k ++)
			Gcd[k * i][k * j] = k, A[k * i][k * j] = i * j * k;

There is still the same effect as the Ehrlich sieve for prime numbers. It is not difficult to understand after learning the sieve method, as long as you have learned it. .
After constructing the matrix, use a double monotonic queue-first process the k number of max in each row and then process the k number of max in each column on the basis of the previous, and get a[i][j] which means k*k sub-matrix For the maximum value, the sum can be calculated at the end.
Code (the structure of the problem solution is not used here):

#include <bits/stdc++.h>
using namespace std;
const int mn = 5001;
 
struct node
{
    
    
    int x, y, val;
};
int a[mn][mn];
 
 
long long gcd(long long a, long long b)
{
    
    
    return b == 0 ? a : gcd(b, a % b);
}
int main()
{
    
    
    int m, n, k;
    while (scanf("%d %d %d", &n, &m, &k) != EOF)
    {
    
    
        for (int i = 1; i <= n; i++)
        {
    
    
            for (int j = 1; j <= m; j++)
            {
    
    
                if (i <= j || a[j][i] == 0)
                    a[i][j] = i * j / gcd(i, j);
                else
                    a[i][j] = a[j][i];
            }
        }
 
        for (int i = 1; i <= n; i++)
        {
    
    
            deque<node> q1;
            for (int j = 1; j <= m; j++)
            {
    
    
                while (!q1.empty() && q1.front().y + k <= j)
                    q1.pop_front();
                while (!q1.empty() && q1.back().val < a[i][j])
                    q1.pop_back();
                q1.push_back(node{
    
     i,j,a[i][j] });
                if (j >= k)
                    a[i][j - k + 1] = q1.front().val;
            }
        }
 
        for (int j = 1; j <= m; j++)
        {
    
    
            deque<node> q1;
            for (int i = 1; i <= n; i++)
            {
    
    
                while (!q1.empty() && q1.front().x + k <= i)
                    q1.pop_front();
                while (!q1.empty() && q1.back().val < a[i][j])
                    q1.pop_back();
                q1.push_back(node{
    
     i,j,a[i][j] });
                if (i >= k)
                    a[i - k + 1][j] = q1.front().val;
            }
        }
 
        long long ans = 0;
        for (int i = 1; i <= n - k + 1; i++)
        {
    
    
            for (int j = 1; j <= m - k + 1; j++)
            {
    
    
                ans += a[i][j];
                //cout << a[i][j] << ' ';
            }
            //cout << endl;
        }
        printf("%lld\n", ans);
    }
 
 
    return 0;
}

Guess you like

Origin blog.csdn.net/ylwhxht/article/details/107454523