2639: 矩形计算|二维莫队
2016-03-14 21:27
381 查看
被刷了一天题现在整个人处于SB状态。。
二维莫队就是直接把横纵坐标都分块,具体的做法就是坐标(x,y)(x,y)属于块⌊x−1n√⌋∗m−−√+⌊y−1m√⌋\lfloor\frac{x-1}{\sqrt{n}}\rfloor*\sqrt{m}+\lfloor\frac{y-1}{\sqrt{m}}\rfloor,然后就开始像一维的那样暴力维护。
两个矩形相互转移的的时候有点乱,算是二维莫队的最难写的地方了
二维莫队就是直接把横纵坐标都分块,具体的做法就是坐标(x,y)(x,y)属于块⌊x−1n√⌋∗m−−√+⌊y−1m√⌋\lfloor\frac{x-1}{\sqrt{n}}\rfloor*\sqrt{m}+\lfloor\frac{y-1}{\sqrt{m}}\rfloor,然后就开始像一维的那样暴力维护。
两个矩形相互转移的的时候有点乱,算是二维莫队的最难写的地方了
#include<set> #include<map> #include<ctime> #include<queue> #include<cmath> #include<cstdio> #include<vector> #include<cstring> #include<cstdlib> #include<iostream> #include<algorithm> using namespace std; int sc() { int i=0,f=1; char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar(); return i*f; } struct W{ int x,y,v; }t[40040]; struct Q{ int x1,x2,y1,y2,p; }q[100010]; bool vis[202][202]; int a[222][222],bl[202][202],Ans[100010],id[202][202],T[40004]; int n,m,tot,mx,bn,bm,ans; bool cmp(W a,W b){return a.v<b.v;} bool cmp1(Q a,Q b) { return bl[a.x1][a.y1]==bl[b.x1][b.y1]?id[a.x2][a.y2]<id[b.x2][b.y2]:bl[a.x1][a.y1]<bl[b.x1][b.y1]; } void insert(int x,int y) { if(!vis[x][y]) { vis[x][y]=1; ans+=2*(T[a[x][y]]++)+1; } } void del(int x,int y) { if(vis[x][y]) { vis[x][y]=0; ans-=2*(--T[a[x][y]])+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++) insert(i,j); } void DEL(int x1,int x2,int y1,int y2) { for(int i=x1;i<=x2;i++) for(int j=y1;j<=y2;j++) del(i,j); } void change(Q a,Q b) { int t; t=min(a.x1-1,b.x2);ADD(b.x1,t,b.y1,b.y2); t=max(a.x2+1,b.x1);ADD(t,b.x2,b.y1,b.y2); t=min(a.y1-1,b.y2);ADD(b.x1,b.x2,b.y1,t); t=max(a.y2+1,b.y1);ADD(b.x1,b.x2,t,b.y2); t=min(b.x1-1,a.x2);DEL(a.x1,t,a.y1,a.y2); t=max(b.x2+1,a.x1);DEL(t,a.x2,a.y1,a.y2); t=min(b.y1-1,a.y2);DEL(a.x1,a.x2,a.y1,t); t=max(b.y2+1,a.y1);DEL(a.x1,a.x2,t,a.y2); } int main() { n=sc(),m=sc(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) id[i][j]=++tot,t[tot].x=i,t[tot].y=j,t[tot].v=sc(); sort(t+1,t+tot+1,cmp); for(int i=1;i<=tot;i++) { if(t[i].v!=t[i-1].v) a[t[i].x][t[i].y]=++mx; else a[t[i].x][t[i].y]=mx; } bn=sqrt(n),bm=sqrt(m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) bl[i][j]=(i-1)/bn*bm+(j-1)/bm; int Q=sc(); for(int i=1;i<=Q;i++) { q[i].p=i; q[i].x1=sc(),q[i].y1=sc(); q[i].x2=sc(),q[i].y2=sc(); if(q[i].x1>q[i].x2)swap(q[i].x1,q[i].x2); if(q[i].y1>q[i].y2)swap(q[i].y1,q[i].y2); } sort(q+1,q+Q+1,cmp1); for(int i=q[1].x1;i<=q[1].x2;i++) for(int j=q[1].y1;j<=q[1].y2;j++) insert(i,j); Ans[q[1].p]=ans; for(int i=2;i<=Q;i++) { change(q[i-1],q[i]); Ans[q[i].p]=ans; } for(int i=1;i<=Q;i++)printf("%d\n",Ans[i]); return 0; }
相关文章推荐
- python之父之语 import this
- 获取string的长度
- 自学MVC开发基础
- 界面跳转
- 复制粘贴出来的悲剧----spring实现文件下载和HttpStatus.CREATED
- 图论相关算法理解和总结
- SpringMVC——注解的使用与结果跳转方式
- 自定义View实现正好显示文本
- 多年积累的对JAVA程序员成长之路的总结
- HDU1257 最少拦截系统[DP]
- maven 快照
- Android Fragment 替换覆盖生命周期方法详解
- ViewPager 详解(二)---详解四大函数
- 检测一段字符串是不是数字
- [BZOJ 1042][HAOI2008]硬币购物
- 整理spring零配置(Annotation)
- 修改C盘“用户”文件夹下面某个账户的文件夹名称
- Redis实现键对应多值
- C++第一次上机实验--(2)
- 本周的进度