考虑静态怎么做:枚举右边界,然后枚举上边界,对应的下边界一定单调不降,单调栈维护每一列从当前枚举的右边界向左最长空位的长度,这样是O(nm)的

注意到n>=m,所以m<=2000,可以枚举右边界,然后考虑怎么快速知道当前枚举的右边界向左最长空位的长度

用线段树维护行,每个节点都维护一段连续的列,p[ro][i]表示当i列从ro的区间最上面开始有多少行是全空的,q[ro][i]表示从下,v[ro][i]表示i列向左扩展最大的最大全空正方形的边长,大概是下面这种感觉:



然后p和q合并的时候类似HOTEL那题,看看左右儿子是否全空来决定直接继承还是加上另一段(因为不涉及其他列所以比较好写)

然后合并l行到r行的v的时候用单调递增的单调队列,分别维护左儿子的q和右儿子的p,从左到右扫,维护当前[l,r]里的最大正方形

询问的时候是按顺序把查询区间里的值都合并到一起,注意是按顺序!

#include<iostream>
#include<cstdio>
using namespace std;
const int N=4000005;
int n,m,Q,len[N<<2],ql[N],qr[N],ll,lr,rl,rr;
struct qwe
{
int f[N<<2];
int* operator [](int x)
{
return f+x*m;
}
}a,p,q,v;
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
void ud(int ro,int ls,int rs)
{
ll=rl=1,lr=rr=0;
for(int i=1,j=1;i<=m;i++)
{
while(rl<=rr&&q[ls][qr[rr]]>q[ls][i])
rr--;
qr[++rr]=i;
while(ll<=lr&&p[rs][ql[lr]]>p[rs][i])
lr--;
ql[++lr]=i;
while(ll<=lr&&rl<=rr&&q[ls][qr[rl]]+p[rs][ql[ll]]<i-j+1)
{
if(qr[rl]<=j)
rl++;
if(ql[ll]<=j)
ll++;
j++;
}
v[ro][i]=max(i-j+1,max(v[ls][i],v[rs][i]));
}
for(int i=1;i<=m;i++)
p[ro][i]=(p[ls][i]==len[ls])?len[ls]+p[rs][i]:p[ls][i];
for(int i=1;i<=m;i++)
q[ro][i]=(q[rs][i]==len[rs])?len[rs]+q[ls][i]:q[rs][i];
}
void build(int ro,int l,int r)
{
len[ro]=r-l+1;
if(l==r)
{
for(int i=1;i<=m;i++)
p[ro][i]=q[ro][i]=v[ro][i]=a[l][i];
return;
}
int mid=(l+r)>>1;
build(ro<<1,l,mid);
build(ro<<1|1,mid+1,r);
ud(ro,ro<<1,ro<<1|1);
}
void update(int ro,int l,int r,int x,int y)
{
if(l==r)
{
p[ro][y]=q[ro][y]=v[ro][y]=a[x][y];
return;
}
int mid=(l+r)>>1;
if(x<=mid)
update(ro<<1,l,mid,x,y);
else
update(ro<<1|1,mid+1,r,x,y);
ud(ro,ro<<1,ro<<1|1);
}
int hb(int la,int ro,int l,int r)
{
ll=rl=1,lr=rr=0;
int nw=0;
for(int i=l,j=l;i<=r;i++)
{
while(rl<=rr&&q[la][qr[rr]]>q[la][i])
rr--;
qr[++rr]=i;
while(ll<=lr&&p[ro][ql[lr]]>p[ro][i])
lr--;
ql[++lr]=i;
while(ll<=lr&&rl<=rr&&q[la][qr[rl]]+p[ro][ql[ll]]<i-j+1)
{
if(qr[rl]<=j)
rl++;
if(ql[ll]<=j)
ll++;
j++;
}
nw=max(nw,i-j+1);
}
for(int i=l;i<=r;i++)
p[la][i]=(p[la][i]==len[la])?len[la]+p[ro][i]:p[la][i];
for(int i=l;i<=r;i++)
q[la][i]=(q[ro][i]==len[ro])?len[ro]+q[la][i]:q[ro][i];
len[la]+=len[ro];
return nw;
}
int ques(int ro,int l,int r,int x,int xx,int y,int yy)
{
if(l==x&&r==xx)
{
int nw=hb(0,ro,y,yy);
for(int i=y;i<=yy;i++)
nw=max(nw,min(i-y+1,v[ro][i]));
return nw;
}
int mid=(l+r)>>1;
if(xx<=mid)
return ques(ro<<1,l,mid,x,xx,y,yy);
else if(x>mid)
return ques(ro<<1|1,mid+1,r,x,xx,y,yy);
else
{
int nw=ques(ro<<1,l,mid,x,mid,y,yy);
return max(nw,ques(ro<<1|1,mid+1,r,mid+1,xx,y,yy));//因为要求按从前往后的顺序合并所以不能直接max两个函数,max的时候处理顺序可能会反
}
}
int main()
{
n=read(),m=read(),Q=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
a[i][j]=read();
build(1,1,n);
while(Q--)
{
int o=read();
if(o==0)
{
int x=read(),y=read();
a[x][y]^=1;
update(1,1,n,x,y);
}
else
{
int x=read(),y=read(),xx=read(),yy=read();
for(int i=1;i<=m;i++)
p[0][i]=q[0][i]=v[0][i]=0;
len[0]=0;
printf("%d\n",ques(1,1,n,x,xx,y,yy));
}
}
return 0;
}

loj #6302. 「CodePlus 2018 3 月赛」寻找车位【线段树+单调队列】的更多相关文章

  1. @loj - 6353@「CodePlus 2018 4 月赛」组合数问题 2

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 请你找到 k 个不同的组合数,使得对于其中任何一个组合数 \(C ...

  2. LOJ#6354. 「CodePlus 2018 4 月赛」最短路[最短路优化建图]

    题意 一个 \(n\) 个点的完全图,两点之间的边权为 \((i\ xor\ j)*C\) ,同时有 \(m\) 条额外单向路径,问从 \(S\) 到 \(T\) 的最短路. \(n\leq 10^5 ...

  3. @loj - 6354@「CodePlus 2018 4 月赛」最短路

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 企鹅国中有 N 座城市,编号从 1 到 N . 对于任意的两座城 ...

  4. LOJ #2831. 「JOISC 2018 Day 1」道路建设 线段树+Link-cut-tree

    用 LCT 维护颜色相同连通块,然后在线段树上查一下逆序对个数就可以了. code: #include <cstdio> #include <algorithm> #inclu ...

  5. 【LibreOJ】#6354. 「CodePlus 2018 4 月赛」最短路 异或优化建图+Dijkstra

    [题目]#6354. 「CodePlus 2018 4 月赛」最短路 [题意]给定n个点,m条带权有向边,任意两个点i和j还可以花费(i xor j)*C到达(C是给定的常数),求A到B的最短距离.\ ...

  6. [LOJ#6259]「CodePlus 2017 12 月赛」白金元首与独舞

    [LOJ#6259]「CodePlus 2017 12 月赛」白金元首与独舞 试题描述 到河北省 见斯大林 / 在月光下 你的背影 / 让我们一起跳舞吧 うそだよ~ 河北省怎么可能有 Stalin. ...

  7. loj #6250. 「CodePlus 2017 11 月赛」找爸爸

    #6250. 「CodePlus 2017 11 月赛」找爸爸 题目描述 小 A 最近一直在找自己的爸爸,用什么办法呢,就是 DNA 比对. 小 A 有一套自己的 DNA 序列比较方法,其最终目标是最 ...

  8. [LOJ 6249]「CodePlus 2017 11 月赛」汀博尔

    Description 有 n 棵树,初始时每棵树的高度为 H_i,第 i 棵树每月都会长高 A_i.现在有个木料长度总量为 S 的订单,客户要求每块木料的长度不能小于 L,而且木料必须是整棵树(即不 ...

  9. [LOJ 6248]「CodePlus 2017 11 月赛」晨跑

    Description “无体育,不清华”.“每天锻炼一小时,健康工作五十年,幸福生活一辈子” 在清华,体育运动绝对是同学们生活中不可或缺的一部分.为了响应学校的号召,模范好学生王队长决定坚持晨跑.不 ...

随机推荐

  1. BZOJ 3363 POJ 1985 Cow Marathon 树的直径

    题目大意:给出一棵树.求两点间的最长距离. 思路:裸地树的直径.两次BFS,第一次随便找一个点宽搜.然后用上次宽搜时最远的点在宽搜.得到的最长距离就是树的直径. CODE: #include < ...

  2. 【转载】分布式系统理论基础 - 一致性、2PC和3PC

    引言 狭义的分布式系统指由网络连接的计算机系统,每个节点独立地承担计算或存储任务,节点间通过网络协同工作.广义的分布式系统是一个相对的概念,正如Leslie Lamport所说[1]: What is ...

  3. 使用 Docker 在 Linux 上托管 ASP.NET Core 应用程序

    说在前面 在阅读本文之前,您必须对 Docker 的中涉及的基本概念以及常见命令有一定了解,本文侧重实战,不会对相关概念详述. 同时请确保您本地开发机器已完成如下安装: Docker 18.06 或更 ...

  4. Struts拦截器(转)

    xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC &qu ...

  5. 《Unix网络编程》中的错误处理函数

    #include "net.h" #include <syslog.h> // syslog() int daemon_proc; static void err_do ...

  6. 李洪强iOS开发之-入门指南

    李洪强iOS开发之-入门指南 1零基础小白如何进行iOS系统学习 首先,学习目标要明确:其次,有了目标,要培养兴趣,经常给自己一些正面的反馈,比如对自己的进步进行鼓励,在前期小步快走:再次,学技术最重 ...

  7. LeetCode(67)题解: Add Binary

    https://leetcode.com/problems/add-binary/ 题目: Given two binary strings, return their sum (also a bin ...

  8. collection 模块 双端队列

    单端队列 用于同一进程中的队列,可以叫做单进程队列. queue 遵循先进先出,先进去的必须先出来 1.先进先出: impore queue q = queue.Queue() 实例化一个对象 q.p ...

  9. 初学unity 3D 遇到的一个问题--预制体选项没有找到。

    没有找到预制体这个选项. 我的工程如下:

  10. O4编译 在 PingCAP 的一些技术挑战

    在 PingCAP 的一些技术挑战 http://www.zenlife.tk/challenge-at-pingcap.md 在 PingCAP 的一些技术挑战 2018-06-02 事务优化 AC ...