题目链接

二维莫队,按x,y坐标一起分块.(x,y)的所属的块为 x/sq(n)*sq(m) + y/sq(m)

排序时按照(左下点所在块,右上点的标号)排序

排序后 先得出一个询问的答案,然后利用上一个询问的矩形与当前矩形位置关系更新答案

转移真的麻烦。。为了避免算重 一定要加个vis[][]

//4432kb	13600ms
#include <cmath>
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=205,M=1e5+5; int n,m,Q,szX,szY,A[N][N],ref[N*N],tm[N*N],bel[N][N],idv[N][N];
LL Ans[M],Now;
bool vis[N][N];
struct Ask
{
int x1,y1,x2,y2,id;
inline bool operator <(const Ask &a)const{
return bel[x1][y1]==bel[a.x1][a.y1]?idv[x2][y2]<idv[a.x2][a.y2]:bel[x1][y1]<bel[a.x1][a.y1];
}
}q[M]; inline int read()
{
int now=0,f=1;register char c=gc();
for(;!isdigit(c);c=gc()) if(c=='-') f=-1;
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now*f;
}
int Find(int x,int r)
{
int l=1,mid;
while(l<r)
if(ref[mid=l+r>>1]>=x) r=mid;
else l=mid+1;
return l;
}
void Discrete()
{
int tot=0,cnt=1;
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j)
ref[idv[i][j]=++tot]=A[i][j]=read();
std::sort(ref+1,ref+1+tot);
for(int i=2; i<=tot; ++i)
if(ref[i]!=ref[i-1]) ref[++cnt]=ref[i];
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j)
A[i][j]=Find(A[i][j],cnt);
}
inline void add(int i,int j){
if(!vis[i][j]) vis[i][j]=1, Now+=2*(tm[A[i][j]]++)+1;
}
inline void subd(int i,int j){
if(vis[i][j]) vis[i][j]=0, Now-=2*(--tm[A[i][j]])+1;
}
void Add(int x1,int x2,int y1,int y2)
{
for(int i=x1; i<=x2; ++i)
for(int j=y1; j<=y2; ++j) add(i,j);
}
void Subd(int x1,int x2,int y1,int y2)
{
for(int i=x1; i<=x2; ++i)
for(int j=y1; j<=y2; ++j) subd(i,j);
}
void Change(int l,int n)
{//now位于las的左下方 左上方 被包含 都是可能的
int t;
t=std::min(q[l].x1-1,q[n].x2), Add(q[n].x1,t,q[n].y1,q[n].y2);
t=std::min(q[l].y1-1,q[n].y2), Add(q[n].x1,q[n].x2,q[n].y1,t);
t=std::max(q[l].x2+1,q[n].x1), Add(t,q[n].x2,q[n].y1,q[n].y2);
t=std::max(q[l].y2+1,q[n].y1), Add(q[n].x1,q[n].x2,t,q[n].y2); t=std::min(q[l].x2,q[n].x1-1), Subd(q[l].x1,t,q[l].y1,q[l].y2);
t=std::min(q[l].y2,q[n].y1-1), Subd(q[l].x1,q[l].x2,q[l].y1,t);
t=std::max(q[l].y1,q[n].y2+1), Subd(q[l].x1,q[l].x2,t,q[l].y2);
t=std::max(q[l].x1,q[n].x2+1), Subd(t,q[l].x2,q[l].y1,q[l].y2);
} int main()
{
n=read(),m=read(); szX=sqrt(n),szY=sqrt(m);
Discrete();
for(int i=1; i<=n; ++i)
for(int j=1; j<=m; ++j)
bel[i][j]=(i-1)/szX*szY+(j-1)/szY;
// for(int i=1; i<=n; ++i,putchar('\n'))
// for(int j=1; j<=m; ++j) printf("%d ",bel[i][j]);
Q=read();
for(int i=1; i<=Q; ++i)
{
q[i].x1=read(),q[i].y1=read(),q[i].x2=read(),q[i].y2=read();
if(q[i].x1>q[i].x2) std::swap(q[i].x1,q[i].x2);//将(x1,y1)设为矩形左下角
if(q[i].y1>q[i].y2) std::swap(q[i].y1,q[i].y2);
q[i].id=i;
}
std::sort(q+1,q+1+Q);
Add(q[1].x1,q[1].x2,q[1].y1,q[1].y2);
Ans[q[1].id]=Now;
for(int i=2; i<=Q; ++i)
Change(i-1,i), Ans[q[i].id]=Now;
for(int i=1; i<=Q; ++i) printf("%lld\n",Ans[i]); return 0;
}

BZOJ.2639.矩形计算(二维莫队)的更多相关文章

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

    <法一>二维莫队,对n和m分别分块后,对块从上到下从左到右依次编号,询问以左上角所在块编号为第一关键字,以右下角标号为第二关键字排序,转移时非常厉害. O(q*n*sqrt(n)). #i ...

  2. [CSP-S模拟测试]:蔬菜(二维莫队)

    题目描述 小$C$在家中开垦了一块菜地,可以抽象成一个$r\times c$大小的矩形区域,菜地的每个位置都种着一种蔬菜.秋天到了,小$C$家的菜地丰收了. 小$C$拟定了$q$种采摘蔬菜的计划,计划 ...

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

    改了两天,终于将T1,T3毒瘤题改完了... T1 施工(单调栈优化DP) 考场上只想到了n*hmaxn*hmaxn的DP,用线段树优化一下变成n*hmaxn*log但显然不是正解 正解是很**的单调 ...

  4. 【Unity3D】计算二维向量夹角(-180到180)

    在Unity3D中,有时候我们需要计算二维向量的夹角.二维向量夹角一般在0~180度之前,可以直接调用Vector2.Angle(Vector2 from, Vector2 to)来计算. 但是在有些 ...

  5. PHP计算二维数组指定元素的和

    array_sum(array_column($arr, 'num')); //计算二维数组指定元素的和 $arr = [ [ 'id'=>1, 'num'=>3, ], [ 'id'=& ...

  6. bzoj 2038 小z的袜子 莫队例题

    莫队,利用可以快速地通过一个问题的答案得到另一问题的答案这一特性,合理地组织问题的求解顺序,将已解决的问题帮助解决当前问题,来优化时间复杂度. 典型用法:处理静态(无修改)离线区间查询问题. 线段树也 ...

  7. bzoj 2038 小Z的袜子 莫队算法

    题意 给你一个长度序列,有多组询问,每次询问(l,r)任选两个数相同的概率.n <= 50000,数小于等于n. 莫队算法裸题. 莫队算法:将序列分为根号n段,将询问排序,以L所在的块为第一关键 ...

  8. BZOJ 4939: [Ynoi2016]掉进兔子洞(莫队+bitset)

    传送门 解题思路 刚开始想到了莫队+\(bitset\)去维护信息,结果发现空间不太够..试了各种奇技淫巧都\(MLE\),最后\(\%\)了发题解发现似乎可以分段做..这道题做法具体来说就是开\(3 ...

  9. BZOJ 3289 Mato的文件管理(莫队+离散化求逆序数)

    3289: Mato的文件管理 Time Limit: 40 Sec  Memory Limit: 128 MB Submit: 2171  Solved: 891 [Submit][Status][ ...

随机推荐

  1. 【网络编程1】网络编程基础-TCP、UDP编程

    网络基础知识 网络模型知识 OSI七层模型:(Open Systems Interconnection Reference Model)开放式通信系统互联参考模型,是国际标准化组织(ISO)提出的一个 ...

  2. How to Repair GRUB2 When Ubuntu Won’t Boot

    Ubuntu and many other Linux distributions use the GRUB2 boot loader. If GRUB2 breaks—for example, if ...

  3. C# 实现UDP打洞通信(一)

    最近研究了一下网络打洞的相关技术,TCP的方式据说可行性不高,各种困难,因此决定采用UDP(UDP是什么就不解释了)的方式. 原理: 我们都知道局域网内的主机想要访问外网的服务器是比较容易的,比如浏览 ...

  4. 最大流算法-最高标号预流推进(HLPP)

    昨天我们学习了ISAP算法,它属于增广路算法的大类.今天学习的算法是预流推进算法中很高效的一类--最高标号预流推进(HLPP). 预流推进 预流推进是一种很直观的网络流算法.如果给到一个网络流让你手算 ...

  5. 《TCP/IP 详解 卷1:协议》第 3 章:链路层

    在体系结构中,我们知道:链路层(或数据链路层)包含为共享相同介质的邻居建立连接的协议和方法,同时,设计链路层的目的是为 IP 模块发送和接受 IP 数据报,链路层可用于携带支持 IP 的辅助性协议,例 ...

  6. tomcat启动报错 ERROR o.a.catalina.session.StandardManager 182 - Exception loading sessions from persiste

    系统:centos6.5 x86_64 jdk: 1.8.0_102 tomcat:8.0.37 tomcat 启动报错: ERROR o.a.catalina.session.StandardMan ...

  7. Go语言规格说明书 之 select语句(Select statements)

    go version go1.11 windows/amd64 本文为阅读Go语言中文官网的规则说明书(https://golang.google.cn/ref/spec)而做的笔记,介绍Go语言的 ...

  8. OCM_第十七天课程:Section7 —》GI 及 ASM 安装配置 _管理和配置 GRID /实施 ASM 故障组 /创建 ACFS 文件系统

    注:本文为原著(其内容来自 腾科教育培训课堂).阅读本文注意事项如下: 1:所有文章的转载请标注本文出处. 2:本文非本人不得用于商业用途.违者将承当相应法律责任. 3:该系列文章目录列表: 一:&l ...

  9. ubuntu 窗口操作快捷键

    alt + space 打开窗口菜单SUPER + A: 搜索或浏览程序 SUPER/alt + tab: 切换窗口 SUPER + L: 进入睡眠状态 SUPER + M:查看日历

  10. GuzzleHttp 请求设置超时时间

    之前调用一个三方的 WEB API,大量的请求超时,导致 PHP 进程被占用完.整个网站一直报 504. 其中一个优化措施就是对三方 API 调用设置超时时间. use GuzzleHttp\Clie ...