传送门:https://ac.nowcoder.com/acm/contest/5667/F 
题意 题目描述 Given a matrix of size$n×m$and an integer$k$,where$A_{i\times j} = lcm(i,j)$the least common multiple of $i$ and $j$. You should determine the sum of the maximums among all $k×k$ submatrices.
输入描述 Only one line containing three integers$n,m,k(1\leq n,m\leq 5000,1\leq k \leq min \{i,j\}$
输出描述 Only one line containing one integer, denoting the answer.
输入 $3$ $4$ $2$
输出 $38$
思路 队友用的是二维ST表AC的,这里是单调队列。
矩阵的所有lcm可以在单调过程中记忆化,复杂度会减少,如果先做预处理(单调前全部计算出会加大复杂度)。
只需要纵向做一遍单调队列,然后把纵向所有的单调队列存在Max二维数组里, 之后在横向做一遍单调队列,这样k*k的方格就能找到最大值了。
Code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 ##include  <bits/stdc++.h>   using  namespace  std;typedef  long  long  ll;typedef  long  double  ld;typedef  pair<double , double > pdd;##define  INF 0x7f7f7f  ##define  mem(a,b) memset(a , b , sizeof(a))  ##define  FOR(i, x, n) for(int i = x;i <= n; i++)  int  gcd (int  a, int  b)  {    return  b == 0  ? a : gcd (b, a % b); } struct  Monotone_queue {     static  const  int  maxn = 5001 ;     int  n, m, k;      int  q[maxn], p[maxn], head, tail;      int  Max[maxn][maxn];     void  read ()       {        cin >> n >> m >> k;     }     void  Monotone ()       {        for (int  i = 1 ;i <= n; i++)         {             head = 1 ; tail = 0 ;             for (int  j = 1 ;j <= m; j++)             {                 int  val = i * j / gcd (i, j);                 while (head <= tail && q[tail] <= val)                     tail--;                 q[++tail] = val;                 p[tail] = j;                 while (head <= tail && p[head] <= j - k)                     head++;                 if (j >= k)                     Max[i][j - k + 1 ] = q[head];             }         }     }     ll ans = 0 ;     void  value ()       {        for (int  j = 1 ; j<= m - k + 1 ; j++)         {             head = 1 ; tail = 0 ;             for (int  i = 1 ;i <= n; i++)             {                 int  val = Max[i][j];                 while (head <= tail && q[tail] <= val)                     tail--;                 q[++tail] = val;                 p[tail] = i;                 while (head <= tail && p[head] <= i - k)                     head++;                 if (i >= k)                     ans += q[head];             }         }         cout << ans << endl;     } }Worker; void  solve ()  {    Worker.read ();     Worker.Monotone ();     Worker.value (); } signed  main ()  {    ios_base::sync_with_stdio (false );           ##ifdef  FZT_ACM_LOCAL      freopen ("in.txt" , "r" , stdin);     freopen ("out.txt" , "w" , stdout); ##else       ios::sync_with_stdio (false );     int  T = 1 ;          while (T--)         solve (); ##endif       return  0 ; } 
 
deque模拟单调队列 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 struct num{     int  index, x; }; deque<num> q;  deque<num> p;  int  s[2 ][10000005 ];int  cnt  =  1 ;void  solve () {     int  n, k, x;     num t;     cin >> n >> k;     for (int  i  =  1 ;i <= n; i++)     {         cin >> x;         t.index = i; t.x = x;         while (!q.empty() && x >= q.back().x)         {             q.pop_back();         }         while (!p.empty() && x <= p.back().x)         {             p.pop_back();         }         q.push_back(t);         p.push_back(t);         while (i - k >= q.front().index)         {             q.pop_front();         }         while (i - k >= p.front().index)         {             p.pop_front();         }         if (i >= k)         {             s[0 ][cnt] = q.front().x;             s[1 ][cnt] = p.front().x;             cnt++;         }     }     for (int  i  =  1 ;i < cnt; i++)         cout << s[1 ][i] << " " ;     cout << endl;     for (int  i  =  1 ;i < cnt; i++)         cout << s[0 ][i] << " " ;     cout << endl; } 
 
数组模拟单调队列 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 struct  Monotone_queue {    static  const  int  maxn = 10000005 ;     int  n, k, a[maxn];      int  q[maxn], p[maxn], head, tail;      void  read ()       {        cin >> n >> k;         for (int  i = 1 ;i <= n; i++)             cin >> a[i];     }     void  Monotone_min ()       {        head = 1 ; tail = 0 ;         for (int  i = 1 ;i <= n; i++)         {             while (head <= tail && q[tail] >= a[i])             {                 tail--;             }             q[++tail] = a[i];             p[tail] = i;             while (p[head] <= i - k)                 head++;             if (i >= k)                 cout << q[head] << " " ;         }         cout << endl;     }     void  Monotone_max ()       {        head = 1 ; tail = 0 ;         for (int  i = 1 ;i <= n; i++)         {             while (head <= tail && q[tail] <= a[i])             {                 tail--;             }             q[++tail] = a[i];             p[tail] = i;             while (p[head] <= i - k)                 head++;             if (i >= k)                 cout << q[head] << " " ;         }         cout << endl;     } }Worker; 
 
本文作者:jujimeizuo 本文地址 : https://blog.jujimeizuo.cn/2020/07/14/2020-nowcoder-shujia-2-f/  本博客所有文章除特别声明外,均采用 CC BY-SA 3.0 协议。转载请注明出处!