HAOI2007 理想的正方形
这个题真难写(大雾
其实还是很好想的,因为我们发现每一行的最大/小值是可以用单调队列维护的,每一列的也是可以用单调队列维护的,所以直接用单调队列分别维护行和列即可。
有大神的做法是先把每列的结果处理出来之后计算,我是直接两边一起进行……不过其实都一样,我的代码相比之下要长上一些。单调队列不是很好调,要注意别写错了。
当然这道题st表分别维护行列也是可以过的,不过要慢一点。
看一下代码。
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<set> #include<queue> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar('\n') using namespace std; typedef long long ll; const int M = 1005; const int INF = 1000000009; int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } struct node { int mval,mpos,bval,bpos; }qy[M][M],qx[M]; int a,b,n,g[M][M],headm[M],tailm[M],headb[M],tailb[M],minn = INF,ansm[1005],ansb[1005]; int main() { a = read(),b = read(),n = read(); rep(i,1,a) rep(j,1,b) g[i][j] = read(); rep(i,1,b) { headm[i] = headb[i] = 1,tailm[i] = tailb[i] = 0; rep(j,1,n) { while(headm[i] <= tailm[i] && qy[tailm[i]][i].mval >= g[j][i]) tailm[i]--; qy[++tailm[i]][i].mval = g[j][i],qy[tailm[i]][i].mpos = j; while(headb[i] <= tailb[i] && qy[tailb[i]][i].bval <= g[j][i]) tailb[i]--; qy[++tailb[i]][i].bval = g[j][i],qy[tailb[i]][i].bpos = j; } //ansm[i] = qy[headm][i].mval,ansm; } //rep(i,1,b) printf("#%d %d\n",qy[headm[i]][i].mval,qy[headb[i]][i].bval); rep(t,n+1,a+1) { headm[0] = headb[0] = 1,tailm[0] = tailb[0] = 0; rep(i,1,b) { while(headm[0] <= tailm[0] && qx[tailm[0]].mval >= qy[headm[i]][i].mval) tailm[0]--; qx[++tailm[0]].mval = qy[headm[i]][i].mval,qx[tailm[0]].mpos = i; while(headm[0] <= tailm[0] && qx[headm[0]].mpos < qx[tailm[0]].mpos - n + 1) headm[0]++; while(headb[0] <= tailb[0] && qx[tailb[0]].bval <= qy[headb[i]][i].bval) tailb[0]--; qx[++tailb[0]].bval = qy[headb[i]][i].bval,qx[tailb[0]].bpos = i; while(headb[0] <= tailb[0] && qx[headb[0]].bpos < qx[tailb[0]].bpos - n + 1) headb[0]++; if(i >= n) { //printf("$%d %d\n",qx[headb[0]].bval,qx[headm[0]].mval); minn = min(minn,qx[headb[0]].bval - qx[headm[0]].mval); } while(headm[i] <= tailm[i] && qy[tailm[i]][i].mval >= g[t][i]) tailm[i]--; qy[++tailm[i]][i].mval = g[t][i],qy[tailm[i]][i].mpos = t; while(headm[i] <= tailm[i] && qy[headm[i]][i].mpos < t - n + 1) headm[i]++; while(headb[i] <= tailb[i] && qy[tailb[i]][i].bval <= g[t][i]) tailb[i]--; qy[++tailb[i]][i].bval = g[t][i],qy[tailb[i]][i].bpos = t; while(headb[i] <= tailb[i] && qy[headb[i]][i].bpos < t - n + 1) headb[i]++; } } printf("%d\n",minn); return 0; }
当你意识到,每个上一秒都成为永恒。