bzoj1047/luogu2216 理想的正方形 (单调队列)

开b组单调队列,分别维护此时某一列中的最大/最小值

然后我每次把它们的头取出来,塞到维护行的单调队列里,就是n*n的最大/最小值

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define CLR(a,x) memset(a,x,sizeof(a))
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=1e3+10;
 7 
 8 inline ll rd(){
 9     ll x=0;char c=getchar();int neg=1;
10     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
11     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
12     return x*neg;
13 }
14 
15 struct Q{
16     int q[maxn][2],h,t;
17     inline void psh(int x,int y,bool b){
18         while(h&&h>=t&&(b?q[h][0]<=x:q[h][0]>=x)) h--;
19         q[++h][0]=x,q[h][1]=y;
20         if(!t) t=h;
21     }
22     inline int pop(int lim){
23         while(h>t&&q[t][1]<=lim) t++;
24         return q[t][0];
25     }
26     inline void clr(){h=t=0;}
27 }ama[maxn],ami[maxn],bma,bmi;
28 int N,A,B,arr[maxn][maxn];
29 
30 int main(){
31     //freopen("","r",stdin);
32     int i,j,k;
33     A=rd(),B=rd();N=rd();
34     for(i=1;i<=A;i++){
35         for(j=1;j<=B;j++)
36             arr[i][j]=rd();
37     }
38     int ans=2e9;
39     for(i=1;i<=A;i++){
40         for(j=1;j<=B;j++){
41             ama[j].psh(arr[i][j],i,1);
42             ami[j].psh(arr[i][j],i,0);
43         }
44         if(i>=N){
45             bma.clr(),bmi.clr();
46             for(j=1;j<=B;j++){
47                 int a=ama[j].pop(i-N),b=ami[j].pop(i-N);
48                 bma.psh(a,j,1);
49                 bmi.psh(b,j,0);
50                 if(j>=N) ans=min(ans,bma.pop(j-N)-bmi.pop(j-N));
51             }
52         }
53     }
54     printf("%d\n",ans);
55     return 0;
56 }

 

posted @ 2018-11-13 08:17  Ressed  阅读(125)  评论(0编辑  收藏  举报