[luogu4259]寻找车位
考虑一个分治的做法:按行分治,将所有区间分为两类——经过分割线的、在左/右区间内部,后者显然可以递归下取,考虑前者
先求出出该行上每一列向上和向下的最大长度,记作$up_{i}$和$down_{i}$,然后枚举左端点$l$,找到最小的右端点$r$满足$r-l+1\le min_{i=l}^{r}up_{i}+\min_{i=l}^{r}down_{i}$(否则减小$r$一定不劣)
此时$r$具有单调性,再用一个单调队列维护即可,但时间复杂度为$o(qnm\log_{2}n)$,甚至劣于$o(qnm)$的暴力,因此需要优化
事实上,分治的很多过程都是重复的,即用线段树来维护区间,对于一个完全包含的区间,我们不需要搜下去,可以直接从该点得到答案
具体的,对于每一个区间:1.预处理出$up_{i}$和$down_{i}$;2.预处理出每一个$l$对应的$r$;3.维护第2项的子树最大值,合并的维护$o(m)$暴力即可,总复杂度为$o(nm+qm\log_{2}n)$
细节:关于$up_{i}$和$down_{i}$的处理另一种方法是求出每一个区间前后缀最长的1,根据子区间答案即可得到(而不保存$up_{i}$和$down_{i}$)

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 4000005
4 #define L (k<<1)
5 #define R (L+1)
6 #define mid (l+r>>1)
7 #define y1 y11
8 struct ji{
9 int l,r;
10 };
11 deque<int>q1,q2;
12 vector<ji>zero,v[N<<2];
13 vector<int>vv,f[N<<2],mx[N<<2];
14 int n,m,q,p,x,y,x1,y1,x2,y2,ans;
15 vector<ji> merge(vector<ji>x,vector<ji>y,int l1,int l2){
16 vector<ji>v;
17 for(int i=0;i<m;i++){
18 v.push_back(ji{0,0});
19 if (x[i].l<l1)v[i].l=x[i].l;
20 else v[i].l=l1+y[i].l;
21 if (y[i].r<l2)v[i].r=y[i].r;
22 else v[i].r=l2+x[i].r;
23 }
24 q1.clear(),q2.clear(),vv.clear();
25 for(int i=0,j=-1;i<m;i++){
26 while ((j<m)&&((j<i)||(j-i+1<=x[q1.front()].r+y[q2.front()].l))){
27 if (++j==m)break;
28 while ((!q1.empty())&&(x[q1.back()].r>=x[j].r))q1.pop_back();
29 q1.push_back(j);
30 while ((!q2.empty())&&(y[q2.back()].l>=y[j].l))q2.pop_back();
31 q2.push_back(j);
32 }
33 vv.push_back(j-1);
34 while ((!q1.empty())&&(q1.front()<=i))q1.pop_front();
35 while ((!q2.empty())&&(q2.front()<=i))q2.pop_front();
36 }
37 return v;
38 }
39 void up(int k,int l,int r){
40 v[k]=merge(v[L],v[R],mid-l+1,r-mid);
41 f[k]=vv;
42 for(int i=0;i<m;i++)mx[k][i]=max(max(mx[L][i],mx[R][i]),f[k][i]);
43 }
44 void build(int k,int l,int r){
45 for(int i=0;i<m;i++){
46 f[k].push_back(0);
47 mx[k].push_back(0);
48 }
49 if (l==r){
50 for(int i=1;i<=m;i++){
51 scanf("%d",&p);
52 v[k].push_back(ji{p,p});
53 f[k][i]=mx[k][i]=i-1-(p^1);
54 }
55 return;
56 }
57 build(L,l,mid);
58 build(R,mid+1,r);
59 up(k,l,r);
60 }
61 void update(int k,int l,int r,int x,int y){
62 if (l==r){
63 v[k][y].l^=1;
64 v[k][y].r^=1;
65 f[k][y]=mx[k][y]=y-(v[k][l].l^1);
66 return;
67 }
68 if (x<=mid)update(L,l,mid,x,y);
69 else update(R,mid+1,r,x,y);
70 up(k,l,r);
71 }
72 vector<ji> query(int k,int l,int r,int x,int y,int xx,int yy){
73 if ((l>y)||(x>r))return zero;
74 if ((x<=l)&&(r<=y)){
75 for(int i=xx;i<=yy;i++)ans=max(ans,min(mx[k][i],yy)-i+1);
76 return v[k];
77 }
78 int ll=min(mid,y)-max(l,x),lr=min(r,y)-max(mid+1,x);
79 vector<ji>vl,vr;
80 vl=query(L,l,mid,x,y,xx,yy);
81 vr=query(R,mid+1,r,x,y,xx,yy);
82 vl=merge(vl,vr,max(ll+1,0),max(lr+1,0));
83 for(int i=xx;i<=yy;i++)ans=max(ans,min(vv[i],yy)-i+1);
84 return vl;
85 }
86 int main(){
87 scanf("%d%d%d",&n,&m,&q);
88 build(1,1,n);
89 for(int i=0;i<m;i++)zero.push_back(ji{0,0});
90 for(int i=1;i<=q;i++){
91 scanf("%d",&p);
92 if (!p){
93 scanf("%d%d",&x,&y);
94 update(1,1,n,x,y-1);
95 }
96 else{
97 scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
98 ans=0;
99 query(1,1,n,x1,x2,y1-1,y2-1);
100 printf("%d\n",ans);
101 }
102 }
103 return 0;
104 }
[luogu4259]寻找车位的更多相关文章
- [Code+#3] 寻找车位
Description 给定一个大小为 \(n\times m\) 的 \(01\) 矩阵. 要求支持:单点翻转,询问子矩形内部最大正方形. \(n\times m\leq 4\cdot 10^6,n ...
- loj #6302. 「CodePlus 2018 3 月赛」寻找车位【线段树+单调队列】
考虑静态怎么做:枚举右边界,然后枚举上边界,对应的下边界一定单调不降,单调栈维护每一列从当前枚举的右边界向左最长空位的长度,这样是O(nm)的 注意到n>=m,所以m<=2000,可以枚举 ...
- <停车卫> 产品需求说明书 version 2.0
<停车卫> 产品需求说明书 文档版本号: Version 2.0 文档编号: xxxx 文档密级: 归属部门/项目: 产品名: 停车卫 子系统名: 编写人: kina 编写日期: 2015 ...
- 瞬间读懂什么是互联网思维、大数据、O2O、众筹、红海
1.什么叫大数据? 某必胜客店的电话铃响了,客服人员拿起电话. 客服:必胜客.您好,请问有什么需要我为您服务? 顾客:你好,我想要一份…… 客服:先生,烦请先把您的会员卡号告诉我. 顾客:16846 ...
- 线下市场,选择微信小程序从未显得如此重要
2017 年 1 月 9 日,小程序正式上线,到今日,3 月 8 号,这个新产品面世刚好满两个月.小程序刚推出便受到全球关注,腾讯股价当天即创逾一个月高位,但关注度先是急速上涨,不久便迅速降温,甚至在 ...
- zz“老司机”成长之路:自动驾驶车辆调试实践
随着自动驾驶技术的发展,一辆新车从被改装到上路需要经过的调试流程也有了许多提升.今天,我希望结合自己之前的调车经验来跟大家分享一下我们是如何将系统的各个模块逐步上车.调试.集成,进而将一辆“新手”车培 ...
- [LeetCode] Find the Celebrity 寻找名人
Suppose you are at a party with n people (labeled from 0 to n - 1) and among them, there may exist o ...
- [LeetCode] Find Minimum in Rotated Sorted Array II 寻找旋转有序数组的最小值之二
Follow up for "Find Minimum in Rotated Sorted Array":What if duplicates are allowed? Would ...
- [LeetCode] Find Minimum in Rotated Sorted Array 寻找旋转有序数组的最小值
Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 migh ...
随机推荐
- 【Docker】(9)---每天5分钟玩转 Docker 容器技术之镜像
镜像是 Docker 容器的基石,容器是镜像的运行实例,有了镜像才能启动容器.为什么我们要讨论镜像的内部结构? 如果只是使用镜像,当然不需要了解,直接通过 docker 命令下载和运行就可以了. 但如 ...
- Go语言核心36讲(Go语言基础知识四)--学习笔记
04 | 程序实体的那些事儿(上) 还记得吗?Go 语言中的程序实体包括变量.常量.函数.结构体和接口. Go 语言是静态类型的编程语言,所以我们在声明变量或常量的时候,都需要指定它们的类型,或者给予 ...
- MyBatis 中实现SQL语句中in的操作 (11)
MyBatis 中实现SQL语句中in的操作 概括:应用myBatis实现SQL查询中IN的操作 1.数据库结构及其数据 2.mapper.xml文件 <?xml version="1 ...
- 4.14——208. 实现 Trie (前缀树)
前缀树(字典树)是经典的数据结构,以下图所示: 本来处理每个节点的子节点集合需要用到set,但是因为输入规定了只有26个小写字母,可以直接用一个[26]的数组来存储. 关于ASCII代码: Java ...
- csp-j 复赛感想
作者:博客园小蔡编程 这次是作者第一次参加csp-j的比赛 内心还是挺激动的 今天,作者就来和大家讨论一下这次csp-j的学习心得和感想 T1 分糖果 这题描述看似复杂 其实就是一道求最大取模的题 L ...
- BUAA 软工 | 从计算机技术中探索艺术之路
项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 第一次作业-热身! 我在这个课程的目标是 掌握软件开发方法学和工程学知识 这个作业在哪个具体方面帮 ...
- 镜头Lens Image circle像圈的解释是什么意思
Image circle镜头中指的是:像圈 像圈(image circle)是指入射光线通过镜头后,在焦平面上呈现出的圆形的明亮清晰的影像幅面,也称像面大小.镜头像圈由镜头光学结构决定,一旦设计完成, ...
- AOP源码解析:AspectJExpressionPointcutAdvisor类
先看看 AspectJExpressionPointcutAdvisor 的类图 再了解一下切点(Pointcut)表达式,它指定触发advice的方法,可以精确到返回参数,参数类型,方法名 1 pa ...
- MVC下垃框的使用
--------------模型-------------------- /// <summary> /// 状态 /// =0 下架 =1 上架 /// </summary> ...
- linux shell 函数返回值问题(超过255)
最近再写一个shell测试的时候出现问题,函数返回值异常 用shell计算斐波那契数列数列,写了一个shell函数,然后调用的,验证的时候我只随便计算了几个数(10以内),确认结果是正确的就提交了,后 ...