题目传送门

题目大意:

  二维平面上有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. Cannot connect to the Docker datemon at tcp://0.0.0.0:2375 is the docker daemon runing?

    一.系统环境: 在Windows 7 64位上,采用Vmware workstation 12安装了CenOS7.5 64位. 二.问题 在CentOS7.5里安装了Docker,启动docker服务 ...

  2. 面试题:Java程序员最常用的20%技术 已看1

    首先常用api(String,StringBuffer/StringBuilder等) 1.集合类,线程类 2.Servlet(很少用纯粹的servlet写,但你要懂,因为很多框架都是基于servle ...

  3. Solidity 没名字的function(){...}作用

    官方解释: 这个叫做fallback function,当有人 1. 只发送以太币给合约而不带任何输入数据:2. 调用smart contract时调起了一个不存在的方法.会触发执行这个方法. Wha ...

  4. 编写高质量代码改善C#程序的157个建议——建议55:利用定制特性减少可序列化的字段

    建议55:利用定制特性减少可序列化的字段 特性(attribute)可以声明式地为代码中的目标元素添加注释.运行时可以通过查询这些托管块中的元数据信息,达到改变目标元素运行时行为的目的.System. ...

  5. 编写高质量代码改善C#程序的157个建议——建议14: 正确实现浅拷贝和深拷贝

    建议14: 正确实现浅拷贝和深拷贝 为对象创建副本的技术称为拷贝(也叫克隆).我们将拷贝分为浅拷贝和深拷贝. 浅拷贝 将对象中的所有字段复制到新的对象(副本)中.其中,值类型字段的值被复制到副本中后, ...

  6. c++基础之struct

    就是让用户自己自定义一个要往里面放各种东西的抽屉 // 声明一个结构体类型 Books struct Books { ]; ]; ]; int book_id; }; int main( ) { Bo ...

  7. windows phone之依赖属性(DependencyProperty)

    Windows Presentation Foundation (WPF) 提供了一组服务,这些服务可用于扩展公共语言运行时 (CLR) 属性的功能,这些服务通常统称为 WPF 属性系统.由 WPF ...

  8. Invoke()的使用

    (最近在看协程) Invoke()方法是一种委托机制 Invoke ( "SendMsg", 3 ), 意思是3秒之后调用 SendMsg() 方法 使用时应该注意以下几点: 1. ...

  9. 一个基于 .NET Core 2.0 开发的简单易用的快速开发框架 - LinFx

    LinFx 一个基于 .NET Core 2.0 开发的简单易用的快速开发框架,遵循领域驱动设计(DDD)规范约束,提供实现事件驱动.事件回溯.响应式等特性的基础设施.让开发者享受到正真意义的面向对象 ...

  10. Agreement has been updated--Edit Phone Number最便捷解决办法(不需要安全提示问题和双重认证)

    2018年06月04日亲测有效: CSDN博客跳转网址: