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 }