题目连接:https://ac.nowcoder.com/acm/contest/5667/Fhtml
题目描述
Given a matrix of size
and an integer
,where
the least common multiple of
and
. You should determine the sum of the maximums among all
submatrices.java
输入描述
Only one line containing three integers
ios
输出描述
Only one line containing one integer, denoting the answer.web
输入
数组
输出
app
队友用的是二维ST表AC的,这里是单调队列。svg
矩阵的全部lcm能够在单调过程当中记忆化,复杂度会减小,若是先作预处理(单调前所有计算出会加大复杂度)。spa
只须要纵向作一遍单调队列,而后把纵向全部的单调队列存在Max二维数组里, 以后在横向作一遍单调队列,这样k*k的方格就能找到最大值了。code
#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++) // const ll mod = 1e9 + 7; // const int maxn = 1e5 + 10; // const double eps = 1e-6; 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; // q是单调队列,p是对应y序号,头节点、尾节点 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); //cin.tie(nullptr); //cout.tie(nullptr); #ifdef FZT_ACM_LOCAL freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #else ios::sync_with_stdio(false); int T = 1; //cin >> T; while(T--) solve(); #endif return 0; }
// 双向队列模拟 struct num{ int index, x; }; deque<num> q; // max deque<num> p; // min 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; }
// 数组模拟 struct Monotone_queue{ static const int maxn = 10000005; int n, k, a[maxn]; // 个数、窗口大小、值 int q[maxn], p[maxn], head, tail; // q是单调队列,p是对应y序号,头节点、尾节点 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;