题目传送门

题目大意:

  二维平面上有q次操作,每次操作可以是添加一个点,也可以是添加一个矩形,问每次操作后,有多少  点-矩形  这样的pair,pair的条件是点被矩形覆盖(边缘覆盖也算)。

思路:

  cdq分治,由于加点和加矩形都既是修改操作又是查询操作,而且两种方式完全不一样,所以用两部分cdq来写。

  先将矩形拆成四个点,并且向左下角扩展一个单元,左下角和右上角的点的权值赋为1,左上角和右下角赋为-1。

  对于加矩形的操作,遇到加的点则修改树状数组,遇到矩形的点查询小于这个矩形的值,并且乘以这个矩形点的权值。

  对于加点的操作,由于往左下角扩展了,所以应该按x从右往左处理,碰到一个矩形点,更新树状数组,碰到加的点,则ans+=sum(m)-sum(y-1),m是y的上界,因为sum(m)是刚好抵消的情况(等于0),而sum(y-1)则代表了有几个矩形的右下角在这个点的下方。

  (还是看代码比较好写,注意树状数组的上界,sum(m)不要作死的用sum(m+1)代替,因为这个自闭了)。

#include<bits/stdc++.h>
using namespace std;
const int maxn=;
int q,tot,m,brr[maxn<<],maxd;
long long ans[maxn],res[maxn<<];
struct node{
int id,x,y,type,val;
}a[maxn<<],b[maxn<<];
inline void Hash(){
sort(brr+,brr++m);
m=unique(brr+,brr++m)-brr-;
for(int i=;i<=tot;i++)
{
a[i].x=lower_bound(brr+,brr++m,a[i].x)-brr;
a[i].y=lower_bound(brr+,brr++m,a[i].y)-brr;
maxd=max(maxd,a[i].y);
}
}
inline void add(int x,int v){
while(x<=m){res[x]+=v, x+= x & (-x);}
}
inline long long sum(int x){
long long tu=;
while(x>){tu+=res[x], x -= x & (-x);}
return tu;
}
inline bool cmpx(const node &a,const node &b){
if(a.x!=b.x)return a.x<b.x;
return a.id<b.id;
}
inline bool cmpx2(const node &a,const node &b){
if(a.x!=b.x)return a.x>b.x;
return a.id<b.id;
} inline void cdq1(int l,int r){//加点
if(l==r)return ; int mid=l+((r-l)>>);
// printf("l:%d r:%d mid:%d\n",l,r,mid);
cdq1(l,mid),cdq1(mid+,r);
int cc=;
for(int i=l;i<=mid;i++)
{
b[++cc]=a[i];
b[cc].id=;
}
for(int i=mid+;i<=r;i++)
{
b[++cc]=a[i];
}
sort(b+,b++cc,cmpx2);
for(int i=;i<=cc;i++)
{
if(b[i].id==){
if(b[i].type==)continue;
add(b[i].y,b[i].val);
// printf("y:%d val:%d\n",b[i].y,b[i].val);
}else{
if(b[i].type==)continue;
ans[b[i].id]+=sum(m)-sum(b[i].y-);//**sum(m+1)
}
}
for(int i=;i<=cc;i++)
{
if(b[i].id==&&b[i].type==)add(b[i].y,-b[i].val);
}
} inline void cdq2(int l,int r){//加矩形
if(l==r)return ;
int mid=l+((r-l)>>);
cdq2(l,mid),cdq2(mid+,r);
int cc=;
for(int i=l;i<=mid;i++)
{
b[++cc]=a[i];
b[cc].id=;
}
for(int i=mid+;i<=r;i++)
{
b[++cc]=a[i];
}
sort(b+,b++cc,cmpx);
for(int i=;i<=cc;i++)
{
if(b[i].id==){
if(b[i].type==)continue;
add(b[i].y,);
}else{
if(b[i].type==)continue;
ans[b[i].id]+=sum(b[i].y)*b[i].val;
}
}
for(int i=;i<=cc;i++)
{
if(b[i].id==&&b[i].type==)add(b[i].y,-);
}
} int main(){
scanf("%d",&q);
tot=;
for(int i=;i<=q;i++)
{
int type,x1,y1,x2,y2;
scanf("%d",&type);
a[++tot].type=type;
a[tot].id=i;
if(a[tot].type==)
{
scanf("%d%d",&x1,&y1);
a[tot].x=x1,a[tot].y=y1;
brr[++m]=x1,brr[++m]=y1;
}
else
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1--,y1--;//tuo zhan ju xin
brr[++m]=x1,brr[++m]=x2,brr[++m]=y1,brr[++m]=y2;
a[tot].x=x1,a[tot].y=y1,a[tot].val=;
a[++tot].x=x1,a[tot].y=y2,a[tot].val=-,a[tot].type=type,a[tot].id=i;
a[++tot].x=x2,a[tot].y=y2,a[tot].val=,a[tot].type=type,a[tot].id=i;
a[++tot].x=x2,a[tot].y=y1,a[tot].val=-,a[tot].type=type,a[tot].id=i;
}
}
Hash(); cdq2(,tot);
cdq1(,tot); for(int i=;i<=q;i++)
{
ans[i]=ans[i]+ans[i-];
printf("%lld\n",ans[i]);
} }

gym101964G Matrix Queries seerc2018k题 cdq分治的更多相关文章

  1. gym101964G Matrix Queries seerc2018g题 数学归纳法+线段树(递归)

    题目传送门 题目大意: 给出2^k大小的白色矩形,q次操作,每次将一行或者一列颜色反转,问总体矩阵的价值,矩阵的价值定义是,如果整个矩阵颜色相同,价值为1,否则就把这个矩阵切成四份,价值为四个小矩阵的 ...

  2. 【BZOJ-1176&2683】Mokia&简单题 CDQ分治

    1176: [Balkan2007]Mokia Time Limit: 30 Sec  Memory Limit: 162 MBSubmit: 1854  Solved: 821[Submit][St ...

  3. BZOJ 2683: 简单题 [CDQ分治]

    同上题 那你为什么又发一个? 因为我用另一种写法又写了一遍... 不用排序,$CDQ$分治的时候归并排序 快了1000ms... #include <iostream> #include ...

  4. bzoj2683简单题 cdq分治

    2683: 简单题 Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 1803  Solved: 731[Submit][Status][Discuss] ...

  5. bzoj 1176: [Balkan2007]Mokia&&2683: 简单题 -- cdq分治

    2683: 简单题 Time Limit: 50 Sec  Memory Limit: 128 MB Description 你有一个N*N的棋盘,每个格子内有一个整数,初始时的时候全部为0,现在需要 ...

  6. 【BZOJ1176】[Balkan2007]Mokia/【BZOJ2683】简单题 cdq分治

    [BZOJ1176][Balkan2007]Mokia Description 维护一个W*W的矩阵,初始值均为S.每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=1600 ...

  7. 【bzoj1176】[Balkan2007]Mokia/【bzoj2683】简单题 CDQ分治+树状数组

    bzoj1176 题目描述 维护一个W*W的矩阵,初始值均为S(题目描述有误,这里的S没有任何作用!).每次操作可以增加某格子的权值,或询问某子矩阵的总权值.修改操作数M<=160000,询问数 ...

  8. BZOJ2683: 简单题(cdq分治 树状数组)

    Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 2142  Solved: 874[Submit][Status][Discuss] Descripti ...

  9. BZOJ 2683 简单题 cdq分治+树状数组

    题意:链接 **方法:**cdq分治+树状数组 解析: 首先对于这道题,看了范围之后.二维的数据结构是显然不能过的.于是我们可能会考虑把一维排序之后还有一位上数据结构什么的,然而cdq分治却可以非常好 ...

随机推荐

  1. SpringAOP03 项目脚手架、自定义注解、织入切面、引介增强

    1 项目脚手架 利用 Maven 进行创建 1.1 利用IDEA创建一个Maven原型项目 技巧01:原型Maven项目是没有webapp文件夹和resources项目文件夹的,需要自己手动创建:创建 ...

  2. ubuntu 设置虚拟机和主机在同一网段

    一.在VMware中将网络连接方式设置为桥接 1.打开VM菜单栏->Settings 2.在弹出的Virtual Machine Setting对话框中点击Network Adapter,在右边 ...

  3. PC端QT源码编译

    转载:http://blog.sina.com.cn/s/blog_c2b97b1d01016x1i.html 1.下载源码(前面已经提到了) 选择合适自己的源码. 先用"uname -a& ...

  4. 关于Rest Framework中View、APIView与GenericAPIView的对比分析

    关于Rest Framework中View.APIView与GenericAPIView的对比分析  https://blog.csdn.net/odyssues_lee/article/detail ...

  5. 关于instanceof测试遇到的问题

    今天上上课 用 instanceof关键字来判断某个对象是否属于某种数据类型.报错  代码如下 package cn.lijun.demo3; import cn.lijun.demo.Person; ...

  6. php抓取网页中的内容

    以下就是几种常用的用php抓取网页中的内容的方法.1.file_get_contentsPHP代码代码如下:>>>>>>>>>>>&g ...

  7. 20169219《移动平台开发实践》移动APP设计应该考虑到的问题

    1.开发流程包括: (1)用户需求分析 (2)产品原型设计 (3)UI视觉设计 (4)APP开发 (5)项目测试 (6)发布 App开发经过UI设计完成之后,便会进入开发阶段. (1)服务器端:编写接 ...

  8. CentOS7-扩容挂载磁盘

    1.1查看新磁盘,可以看到/dev/sdb是新的未挂载的磁盘: [root@localhost ~]# fdisk -l 1.2硬盘分区 ,进入fdisk模式 进入fdisk模式 [root@loca ...

  9. asp.net 中input radio checked 无效

    把Jq代码中的$(...).attr("checked",true) 换成$(...).prop("checked",true) ,

  10. bitest(位集合)------c++程序设计原理与实践(进阶篇)

    标准库模板类bitset是在<bitset>中定义的,它用于描述和处理二进制位集合.每个bitset的大小是固定的,在创建时指定: bitset<4> flags; bitse ...