luogu P2216 [HAOI2007]理想的正方形

传送门

LBA就是强啊...

一开始看这个题的时候还以为一个st表就搞完了

但是交完了T (发现是自己写跪了 updated on 11.06 3 p.m.)

决定还是练一下单调队列 毕竟不太好写

然后这题需要维护两个单调队列分别表示最大最小值

然后再开两级分别维护一行中的最值(x[][])和 上一级单调队列中的最值 (y[][])

这样y[][]存的就不是一列的最值 而是最终正方形中的最值

最后最值就是按左上角角标存在y[][] 直接算就行

(也不知道考试能不能想到)

Time cost:60min

Code:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<queue>
 6 #include<iostream>
 7 #define ms(a,b) memset(a,b,sizeof a)
 8 #define rep(i,a,n) for(int i = a;i <= n;i++)
 9 #define per(i,n,a) for(int i = n;i >= a;i--)
10 #define inf 2147483647
11 using namespace std;
12 typedef long long ll;
13 typedef double D;
14 #define eps 1e-8
15 ll read() {
16     ll as = 0,fu = 1;
17     char c = getchar();
18     while(c < '0' || c > '9') {
19         if(c == '-') fu = -1;
20         c = getchar();
21     }
22     while(c >= '0' && c <= '9') {
23         as = as * 10 + c - '0';
24         c = getchar();
25     }
26     return as * fu;
27 }
28 //head
29 const int N = 1005;
30 int n,m,k;
31 int a[N][N];
32 int head,tail,q[N];
33 int Head,Tail,Q[N];
34 int X[N][N],x[N][N],Y[N][N],y[N][N];
35 int main() {
36     // freopen("in.in","r",stdin);
37     n = read(),m = read(),k = read();
38     // printf("%d %d %d
",n,m,k);
39     rep(i,1,n) rep(j,1,m) a[i][j] = read();
40     rep(i,1,n) {
41         head = tail = Head = Tail = Q[1] = q[1] = 1;
42         rep(j,2,m) {
43             while(Head <= Tail && a[i][Q[Tail]] <= a[i][j]) Tail--;
44             while(head <= tail && a[i][q[tail]] >= a[i][j]) tail--;
45             Q[++Tail] = q[++tail] = j;
46             while(j-Q[Head] >= k) Head++;
47             while(j-q[head] >= k) head++;
48             if(j >= k) {
49                 X[i][j-k+1] = a[i][Q[Head]];
50                 x[i][j-k+1] = a[i][q[head]];
51             }
52         }
53     }
54     //x[n][m-k+1]
55     rep(i,1,m-k+1) {
56         Head = Tail = head = tail = q[1] = Q[1] = 1;
57         rep(j,1,n) {
58             while(Head <= Tail && X[Q[Tail]][i] <= X[j][i]) Tail--;
59             while(head <= tail && x[q[tail]][i] >= x[j][i]) tail--;
60             Q[++Tail] = q[++tail] = j;
61             while(j - Q[Head] >= k) Head++;
62             while(j - q[head] >= k) head++;
63             if(j >= k) {
64                 Y[j-k+1][i] = X[Q[Head]][i];
65                 y[j-k+1][i] = x[q[head]][i];
66             }
67         }
68     }
69     int minn = inf;
70     rep(i,1,n-k+1) rep(j,1,m-k+1) {
71         minn = min(minn,Y[i][j] - y[i][j]);
72     }
73     printf("%d
",minn);
74     return 0;
75 }
View Code

 

> 别忘了 总有人在等着你
原文地址:https://www.cnblogs.com/yuyanjiaB/p/9912984.html