BZOJ 1047 [HAOI2007]理想的正方形 单调队列DP

题解:

刚睡醒写的,总是看不清括号。。。调了半天。。

就是横向一个掉队列,纵向b个单调队列,n^2的求出以(i,j)点为右下角的n*n矩形的最大值和最小值,然后n^2的统计就好~

 

 

View Code
 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cstdio>
 5 #include <algorithm>
 6 
 7 #define N 1111
 8 #define BUG system("pause")
 9 
10 using namespace std;
11 
12 long long a,b,n;
13 long long map[N][N];
14 long long q[N][N],h[N],t[N],s,e,dq[N];
15 long long mx[N][N],ans,mn[N][N];
16 
17 inline void read()
18 {
19     scanf("%lld%d%d",&a,&b,&n);
20     for(long long i=1;i<=a;i++)
21         for(long long j=1;j<=b;j++)
22             scanf("%lld",&map[i][j]);
23 }
24 
25 inline void getmax()
26 {
27     for(long long i=1;i<=b;i++) h[i]=1,t[i]=0;
28     for(long long i=1;i<=a;i++)
29     {
30         for(long long j=1;j<=b;j++)
31         {
32             
33             while(h[j]<=t[j]&&i-q[j][h[j]]+1>n) h[j]++;
34             while(h[j]<=t[j]&&map[q[j][t[j]]][j]<=map[i][j]) t[j]--;
35             q[j][++t[j]]=i;    
36         }
37         e=0; s=1;
38         for(long long j=1;j<=b;j++)
39         {
40             while(s<=e&&j-dq[s]+1>n) s++;
41             while(s<=e&&map[q[dq[e]][h[dq[e]]]][dq[e]]<=map[q[j][h[j]]][j]) e--;
42             dq[++e]=j;
43             mx[i][j]=map[q[dq[s]][h[dq[s]]]][dq[s]];
44         }
45     }
46 }
47 
48 inline void getmin()
49 {
50     for(long long i=1;i<=b;i++) h[i]=1,t[i]=0;
51     for(long long i=1;i<=a;i++)
52     {
53         for(long long j=1;j<=b;j++)
54         {
55             while(h[j]<=t[j]&&i-q[j][h[j]]+1>n) h[j]++;
56             while(h[j]<=t[j]&&map[q[j][t[j]]][j]>=map[i][j]) t[j]--;
57             q[j][++t[j]]=i;    
58         }
59         e=0; s=1;
60         for(long long j=1;j<=b;j++)
61         {
62             while(s<=e&&j-dq[s]+1>n) s++;
63             while(s<=e&&map[q[dq[e]][h[dq[e]]]][dq[e]]>=map[q[j][h[j]]][j]) e--;
64             dq[++e]=j;
65             mn[i][j]=map[q[dq[s]][h[dq[s]]]][dq[s]];
66         }
67     }
68 }
69 
70 inline void go()
71 {
72     getmin();
73     getmax();
74     ans=1LL<<60;
75     for(long long i=n;i<=a;i++)
76         for(long long j=n;j<=b;j++)
77             ans=min(ans,mx[i][j]-mn[i][j]);
78     printf("%lld\n",ans);
79 }
80 
81 int main()
82 {
83     read(),go();
84     return 0;
85 }

 

 

posted @ 2013-03-05 21:33  proverbs  阅读(1010)  评论(0编辑  收藏  举报