一、题目
二、分析
对于二维空间找区间最小值,那么一维的很多好用的都无法用了,这里可以用单调队列进行查找。
先固定一个坐标,然后进行一维的单调队列操作,维护一个区间长度为$b$的最小值,可以确定一个数组$ans$。
对于新数组,进行另一个维度的单调队列操作,找到$a*b$的最小值。(由于英语太差,读题目时理解成了是点在区间左上角的意思)
写的时候一定注意第二次单调队列的对象数组是新数组。
三、AC代码
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 #define ll long long 5 #define Min(a,b) ((a)>(b)?(b):(a)) 6 #define Max(a,b) ((a)>(b)?(a):(b)) 7 const int maxn = 3e3 + 13; 8 ll h[maxn][maxn]; 9 ll ans[maxn][maxn]; 10 11 int que[maxn]; 12 int ql, qr; 13 14 int main() 15 { 16 //freopen("input.txt", "r", stdin); 17 int n, m, a, b; 18 int x, y, z; 19 while(scanf("%d%d%d%d", &n, &m, &a, &b) != EOF) 20 { 21 int i, j; 22 ll g0; 23 scanf("%I64d%d%d%d", &g0, &x, &y, &z); 24 for(i = 1; i <= n; i++) 25 { 26 for(j = 1; j <= m; j++) 27 { 28 h[i][j] = g0; 29 g0 = (1ll*g0*x + y)%z; 30 } 31 } 32 for(i = 1; i <= n; i++) 33 { 34 ql = 0, qr = 0; 35 for(j = 1; j <= m; j++) 36 { 37 while(ql < qr && j - que[ql] >= b) 38 ql++; 39 while(ql < qr && h[i][j] <= h[i][que[qr-1]]) 40 qr--; 41 que[qr++] = j; 42 ans[i][j] = h[i][que[ql]]; 43 } 44 } 45 ll tmp = 0; 46 for(j = b; j <= m; j++) 47 { 48 ql = 0, qr = 0; 49 for(i = 1; i <= n; i++) 50 { 51 while(ql < qr && i - que[ql] >= a) 52 ql++; 53 while(ql < qr && ans[i][j] <= ans[que[qr-1]][j]) 54 qr--; 55 que[qr++] = i; 56 if(i >= a) 57 tmp += ans[que[ql]][j]; 58 } 59 } 60 printf("%I64d ", tmp); 61 } 62 return 0; 63 }