NOIP提高组【JZOJ4817】square
来源:互联网 发布:辽宁大石药业淘宝 编辑:程序博客网 时间:2024/06/06 16:39
Description
Data Constraint
Solution
我们首先可以预处理出f[i][j]表示以(i,j)为右下角的最大正方形的边长。这显然可以在输入时处理出来。f[i][j]=min(f[i−1][j−1],f[i−1][j],f[i][j−1])+1 。对于一个询问(x,y,xx,yy),我们其实是可以二分答案的。假设我们当前二分出来的答案为mid,那么我们就可以在(x+mid-1,y+mid-1,xx,yy)这个区间那里找一个最大正方形,若最大正方形的边长大于mid就往右走。那么现在问题是:如何在(x+mid-1,y+mid-1,xx,yy)这个区间内找一个最大的f[i][j]呢?我们想到用二维rmq来解决。设g[x][y][i][j]表示(i-2x+1 ,j-2y+1 ,i,j)这个区间内的最大的f值。然后设t=log2xx−(x+mid−1) ,k=log2yy−(y+mid−1) ,那么一个询问(x+mid-1,y+mid-1,xx,yy)的中的最大f值则是max(g[t][k][xx][yy],g[t][k][x+mid−1+2t][y+mid−1+2k],g[t][k][x+mid−1+2t][yy],g[t][k][xx][y+mid−1+2k]) 。(若看不懂的话可以手动画一下图,画一下就懂了。)注意一下,log的运算在c++中是很慢的,建议手打,否则你会像博主一样卡了3小时的常还是90分……
代码
#include<iostream>#include<cmath>#include<cstring>#include<cstdio>#include<algorithm>#define ll long longusing namespace std;const int maxn=1005;int a[maxn][maxn],n,i,t,j,k,l,m,p,x,y,xx,yy,r,mid,l1;int f[maxn][maxn],g[11][11][maxn][maxn],ans;int pan(int x,int y){ int i,j,t=0,k=0; while (x+(1<<(t+1))-1<=xx) t++; while (y+(1<<(k+1))-1<=yy) k++; ans=g[t][k][xx][yy]; if (g[t][k][x+(1<<t)-1][y+(1<<k)-1]>ans) ans=g[t][k][x+(1<<t)-1][y+(1<<k)-1]; if (ans<g[t][k][x+(1<<t)-1][yy]) ans=g[t][k][x+(1<<t)-1][yy]; if (ans<g[t][k][xx][y+(1<<k)-1]) ans=g[t][k][xx][y+(1<<k)-1]; return ans;}int get(){ char ch=getchar();int x=0; while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar(); return x;}int main(){ freopen("square.in","r",stdin);freopen("square.out","w",stdout); scanf("%d%d",&n,&m); for (i=1;i<=n;i++) for (j=1;j<=m;j++){ scanf("%d",&a[i][j]); if (a[i][j]) f[i][j]=min(min(f[i-1][j-1],f[i-1][j]),f[i][j-1])+1; g[0][0][i][j]=f[i][j]; } l1=log(n)/log(2); p=log(m)/log(2); for (i=0;i<=l1;i++) for (j=0;j<=p;j++){ if (!i && !j) continue; for (x=(1<<i);x<=n;x++) for (y=(1<<j);y<=m;y++){ if (i){ if (g[i-1][j][x][y]>g[i-1][j][x-(1<<(i-1))][y]) g[i][j][x][y]=g[i-1][j][x][y]; else g[i][j][x][y]=g[i-1][j][x-(1<<(i-1))][y]; } else{ if (g[i][j-1][x][y]>g[i][j-1][x][y-(1<<(j-1))]) g[i][j][x][y]=g[i][j-1][x][y]; else g[i][j][x][y]=g[i][j-1][x][y-(1<<(j-1))]; } } } scanf("%d",&m); while (m){ scanf("%d%d%d%d",&x,&y,&xx,&yy); //x=get();y=get();xx=get();yy=get(); l=0;r=min(yy-y+1,xx-x+1); while (l<r){ mid=(l+r+1)/2; if (pan(x+mid-1,y+mid-1)>=mid) l=mid; else r=mid-1; } printf("%d\n",l); m--; }}
3 0
- NOIP提高组【JZOJ4817】square
- [JZOJ4817]square
- JZOJ4817. square
- jzoj4817 Square
- 【JZOJ4817】square
- JZOJ4817. 【NOIP2016提高A组五校联考4】square 二维rmq
- 【JZOJ4817】【NOIP2016提高A组五校联考4】square
- {题解}[jzoj4817]【NOIP2016提高A组五校联考4】square
- NOIP提高组 单峰
- NOIP提高组 积木
- NOIP提高组 看电影
- NOIP提高组 鼎纹
- NOIP提高组 千帆渡
- NOIP提高组 Brothers
- NOIP提高组 Crisis
- NOIP提高组 Word
- NOIP提高组 闭门造车
- NOIP提高组 爬山
- 服务器上的tomcat偶尔响应变慢
- 【JZOJ4816】【NOIP2016提高A组五校联考4】label
- Android studio两种工程目录视图对比--Using the Android Project View
- 解决Linux关闭终端(关闭SSH等)后运行的程序自动停止
- Android Handler 消息机制(解惑篇)
- NOIP提高组【JZOJ4817】square
- kubernetes1.4新特性:支持两种新的卷插件
- 常用的100linux命令
- Python中numpy的基本统计学
- sqoop 常用命令整理
- 贝叶斯分类器(二)
- 页面修改保存到数据库中乱码
- php处理数组的函数
- windows进程间通信