【NOIP2016提高A组五校联考4】square
来源:互联网 发布:淘宝搜索词分析收费 编辑:程序博客网 时间:2024/05/23 20:55
Description
Solution
比赛的时候就想到了要二分,还有像RMQ一样的弄,就像有一道题叫做妮厨的愤怒(我的博客上有)一样,思想十分的简单,但是我没有打完TAT。
比赛之后推倒重写。
一个f数组
首先需要一个f数组f[i][j]表示以(i,j)为右下角的最大正方形的边长。
这个十分的显然。
二分和二维RMQ
然后,最大最小值明显是用二分的思想来处理。
二分出一个mid表示答案,然后只需要在(x+mid-1,y+mid-1)到(xx,yy)这个范围内找一个最大值就好了。
只用最大值而已,那么明显RMQ值最合适不过的。
然后,这里又有一个需要反思的地方了。
我在用RMQ在(x,y)到(xx,yy)范围内找最大值的时候一开始是用
后来才发现我的RMQ没有学好(主要是用的不多,这题又要卡常数),然后用了个快点的方法:比如一维的RMQ中在[x,y]中找一个最大值,首先求出
那么二维的RMQ也是类似的。
但是之后,还是过不了,只有90分。
卡常
首先是预处理的卡常:
1、k和l我一开始是开到10的,其实9就好了(我没有用换底公式)。
2、为什么k和l要打在前面呢?因为这样预处理的时候i和j的范围就变成了
3、去最大值优化(这个还是很有用的)。
4、去函数优化。
5、其实上面的都不是关键,最重要的是这个优化(开了我3个小时)。电脑搞这个log的速度是非常慢的,所以与其用高级的换底公式还不如直接暴力算出log(速度才
这些优化打了,肯定能过。
Code
#include<iostream>#include<cstdio>#include<cmath>#include<cstring>#include<algorithm>#define fo(i,a,b) for(i=a;i<=b;i++)#define fod(i,a,b) for(i=a;i>=b;i--)using namespace std;const int maxn=1007;int i,j,k,l,t,n,m,cas,r,mid,ans,p,q,yi,er1,lef,rig;int x,y,xx,yy;int a[maxn][maxn],f[maxn][maxn];int g[11][11][maxn][maxn],er[11];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 pan(int xx,int yy,int x,int y){ int i,j,t=0,k=0,ans=0,q; 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(g[t][k][x+(1<<t)-1][yy]>ans)ans=g[t][k][x+(1<<t)-1][yy]; if(g[t][k][xx][y+(1<<k)-1]>ans)ans=g[t][k][xx][y+(1<<k)-1]; return ans;}int main(){// freopen("fan.in","r",stdin);// freopen("fan.out","w",stdout); freopen("square.in","r",stdin); freopen("square.out","w",stdout); scanf("%d%d",&n,&m); er[0]=1; fo(i,1,10)er[i]=er[i-1]*2; fo(i,1,n)fo(j,1,m)a[i][j]=get(); for(i=1;i<=n;i++)for(j=1;j<=m;j++){ if(a[i][j]){ g[0][0][i][j]=g[0][0][i-1][j]; if(g[0][0][i][j-1]<g[0][0][i][j])g[0][0][i][j]=g[0][0][i][j-1]; if(g[0][0][i-1][j-1]<g[0][0][i][j])g[0][0][i][j]=g[0][0][i-1][j-1]; g[0][0][i][j]++; } } for(i=0;(1<<i)<=n;i++){ for(j=0;(1<<j)<=m;j++){ if(i==0&&j==0)continue; for(k=er[i];k<=n;k++) for(l=er[j];l<=m;l++){ if(j==0){ g[i][j][k][l]=g[i-1][j][k][l]; if(g[i-1][j][k-(1<<(i-1))][l]>g[i][j][k][l])g[i][j][k][l]=g[i-1][j][k-(1<<(i-1))][l]; } else { g[i][j][k][l]=g[i][j-1][k][l]; if(g[i][j-1][k][l-(1<<(j-1))]>g[i][j][k][l])g[i][j][k][l]=g[i][j-1][k][l-(1<<(j-1))]; } } } } for(scanf("%d",&cas);cas;cas--){ x=get(),y=get(),xx=get(),yy=get(); if(pan(xx,yy,x,y)==0){ printf("0\n"); continue; } l=0,r=xx-x+1; if(yy-y+1<r)r=yy-y+1; while(l<r){ mid=(l+r+1)/2; if(pan(xx,yy,x+mid-1,y+mid-1)>=mid)l=mid;else r=mid-1; } printf("%d\n",l); }}
- 【NOIP2016提高A组五校联考4】square
- 【NOIP2016提高A组五校联考4】square
- 【NOIP2016提高A组五校联考4】square
- JZOJ4817. 【NOIP2016提高A组五校联考4】square 二维rmq
- JZOJ 4817 【NOIP2016提高A组五校联考4】square
- 【JZOJ4817】【NOIP2016提高A组五校联考4】square
- JZOJ 4817. 【NOIP2016提高A组五校联考4】square
- {题解}[jzoj4817]【NOIP2016提高A组五校联考4】square
- JZOJ【4817】. 【NOIP2016提高A组五校联考4】square
- 【NOIP2016提高A组五校联考4】ksum
- 【NOIP2016提高A组五校联考4】label
- 【NOIP2016提高A组五校联考4】ksum
- 【NOIP2016提高A组五校联考4】label
- 【NOIP2016提高A组五校联考4】label
- ksum 【NOIP2016提高A组五校联考4】
- 【NOIP2016提高A组五校联考4】ksum
- 【NOIP2016提高A组五校联考4】label
- NOIP2016提高A组五校联考4总结
- JobService的使用及源码分析
- SQL for ES
- android studio开发<十一> Library第三方类库源码, Jar包和SO库
- stm32 换了芯片出现了很多错误
- mybatis简单入门
- 【NOIP2016提高A组五校联考4】square
- 《机器管家》的生产者‘北安公司’原来是在我们公司总部取的景
- 《初入linux》--第三部分-man命令与输入输出
- iOS中UITextField使用详解
- Linux_USB_gadget设备驱动
- 使用Nexus搭建Maven私服
- 关于webapp的浏览记录写法
- MySQL的查询、子查询及连接查询
- <context annotation-config />标签意义: