二维莫队(离线)

什么是莫队算法

莫队算法



何谓二维莫队

区别与一维莫队,无非就是放在了二维上而已。



适用范围

同一维莫队。



二维莫队的思路

依然是将问题离线,将整张图(设长为$n$宽为$m$),我们分别将长和宽分成根号块,然后将其编号,对于每一组询问,我们将其一个端点按块的大小排序,另一个端点直接按大小排序,可以类比一维莫队。



时间复杂度分析

时间复杂度分析是我自己$YY$的,有可能有错,不要声张,不要消费,私信我就好了。

假设询问次数为$q$,长和宽同阶,所以都设为$n$,设块长为$\sqrt{n}$,那么我们会有$n$块,现在对于每一次询问,对于按块大小排序的端点,其最多会移动长为$2\times \sqrt{n}$的距离(从一个角到另一个角),而对于直接按大小的端点,对于每一个块,都有可能会移动到整张图的一个角,再移动回来,而这个次数是$q$次,再加上要将问题排序,所以时间复杂度为:$\Theta(q\log q+q\times n\sqrt{n})$。



代码时刻

struct rec{int x0,y0,x2,y2,pos,id;}e[100001];
int r,c,q;
int sqrr,sqrc;
int ans[100001];
int uu,dd,ll,rr;
bool cmp(rec a,rec b){return a.x0/sqrr==b.x0/sqrr?(a.y0/sqrc==b.y0/sqrc?(a.x2/sqrr==b.x2/sqrr?a.y2/sqrc<b.y2/sqrc:a.x2<b.x2):a.y0<b.y0):a.x0<b.x0;}
int main()
{
	scanf("%d%d%d",&r,&c,&q);
	sqrr=sqrt(r);sqrc=sqrt(c);
	for(int i=1;i<=q;i++)
	{
		scanf("%d%d%d%d",&e[i].x0,&e[i].y0,&e[i].x2,&e[i].y2);
		e[i].id=i;
	}
	sort(e+1,e+q+1,cmp);
	ll=rr=e[1].x0;
	uu=dd=e[1].y0;
	for(int i=1;i<=q;i++)
	{
		while(uu>e[i].y0)upd(--uu,ll,rr,0,1);
		while(uu<e[i].y0)upd(uu++,ll,rr,0,0);
		while(dd<e[i].y2)upd(++dd,ll,rr,0,1);
		while(dd>e[i].y2)upd(dd--,ll,rr,0,0);
		while(ll>e[i].x0)upd(--ll,uu,dd,1,1);
		while(ll<e[i].x0)upd(ll++,uu,dd,1,0);
		while(rr<e[i].x2)upd(++rr,uu,dd,1,1);
		while(rr>e[i].x2)upd(rr--,uu,dd,1,0);
		ans[e[i].id]=ans[0];
	}
	for(int i=1;i<=q;i++)printf("%d\n",ans[i]);
	return 0;
}


例题

$\alpha.$蔬菜

原文地址:https://www.cnblogs.com/wzc521/p/11577569.html

时间: 2024-08-29 15:37:03

二维莫队(离线)的相关文章

【二维莫队】【二维分块】bzoj2639 矩形计算

<法一>二维莫队,对n和m分别分块后,对块从上到下从左到右依次编号,询问以左上角所在块编号为第一关键字,以右下角标号为第二关键字排序,转移时非常厉害. O(q*n*sqrt(n)). #include<cstdio> #include<algorithm> #include<cmath> using namespace std; #define N 201 #define M 100001 struct LiSan{int p,v;}t[N*N]; bool

BZOJ.2639.矩形计算(二维莫队)

题目链接 二维莫队,按x,y坐标一起分块.(x,y)的所属的块为 x/sq(n)*sq(m) + y/sq(m) 排序时按照(左下点所在块,右上点的标号)排序 排序后 先得出一个询问的答案,然后利用上一个询问的矩形与当前矩形位置关系更新答案 转移真的麻烦..为了避免算重 一定要加个vis[][] //4432kb 13600ms #include <cmath> #include <cstdio> #include <cctype> #include <algor

csp-s模拟测试50(9.22)「施工(单调栈优化DP)」&#183;「蔬菜(二维莫队???)」&#183;「联盟(树上直径)」

改了两天,终于将T1,T3毒瘤题改完了... T1 施工(单调栈优化DP) 考场上只想到了n*hmaxn*hmaxn的DP,用线段树优化一下变成n*hmaxn*log但显然不是正解 正解是很**的单调栈 可以想象到最优情况一定是将两端高于中间的一段平原填成一段平的坑,不然如果坑内存在高度差那么我们即使只将一部分抬升也肯定没有用处,并且如果中间的坑已经高于了两端,再向上升也肯定不优,然后就中间的坑可以很很小,也可以很长,对于这个模型我们首先想到n^2*h的DP 设当前表示的f[i]表示当前到了i节

BZOJ 2038 小Z的袜子(hose) (莫队离线)

题目地址:BZOJ 2038 裸的莫队算法. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdio.h> #includ

静态二维数点问题离线解法的一种设想

先将所有点和询问读下来,按每一维离散化. 之后开n个vector,表示横坐标为i的点.可以\(O(n)\)处理二维前缀和. 查询时在vector中lower_bound,差分即可. 总时间复杂度\(O(n\log n)\),空间复杂度\(O(n)\),常数可能比扫描线小. 原文地址:https://www.cnblogs.com/utopia999/p/9813330.html

莫队算法小结(Markdown版)

wtf,最近挖坑有点小多啊,没办法>_<容我先把糖果公园A了再来写这个吧= =看看今天能不能A掉 好吧,我承认我第二天才把糖果公园A掉>_<下面把这篇小结补上 首先众所周知的是莫队算法是要把询问先按左端点属于的块排序,再按右端点排序 复杂度就先不证了,有兴趣的同学可以自己YY下或者查阅资料 下面举几个例子详细说明 1.小Z的袜子 Description: 给定一个序列m个询问 每次询问: 区间中选两个数,两个数相等的概率 若概率为0则输出01 仔细观察发现,令x表示x这个值出现的次

莫队算法小结

唔,想有更加舒爽的阅读体验请移步http://mlz000.logdown.com/posts/252433-mo-algorithm-summary 首先众所周知的是莫队算法是要把询问先按左端点属于的块排序,再按右端点排序 复杂度就先不证了,有兴趣的同学可以自己YY下或者查阅资料 下面举几个例子详细说明 1.小Z的袜子 Description: 给定一个序列m询问 每次询问: 区间中选两个数,两个数相等的概率 若概率为则输出0/1 仔细观察发现,令x表示x个值出现的次数,则每次询问[l,r]区

BZOJ2120数颜色(带修改莫队)

2120: 数颜色 Time Limit: 6 Sec  Memory Limit: 259 MBSubmit: 7384  Solved: 2998[Submit][Status][Discuss] Description 墨 墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2. R P Col 把第P支画笔替换为颜色Col.为了满足墨墨的要求,你知道你需要

hdu 5381 The sum of gcd 莫队+预处理

The sum of gcd Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem Description You have an array A,the length of A is nLet f(l,r)=∑ri=l∑rj=igcd(ai,ai+1....aj) Input There are multiple test cases. The first line