题目传送门

题目大意:

  二维平面上有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. 生成ico格式图标

    ico格式可参考如下链接: http://msdn.microsoft.com/en-us/library/ms997538.aspx http://en.wikipedia.org/wiki/ICO ...

  2. hibernate 框架的简单使用

    <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuratio ...

  3. 面试题:Java必知必会:异常机制详解 背1

    一.Java异常概述 在Java中,所有的事件都能由类描述,Java中的异常就是由java.lang包下的异常类描述的. Trowable是所有异常的超类.  他的常用方法printStackTrec ...

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

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

  5. 新浪SAE高级开发者认证通过

    如题,新浪SAE高级开发者认证通过,申请的方式为提交开源项目地址,用的是如下的项目 http://jqext.sinaapp.com/ 之前该项目是部署在 mopaas 上的,在拿到高级开发者资格后迁 ...

  6. Intent对象若干数据项的含义总结

    Intent作为组件之间通信的手段和协议,包含了诸如Action.Data.Type.Category.Component.Extras和Flags等数据项,各自拥有各自的含义和作用.当调用组件发出一 ...

  7. Flask框架 之 路由和视图详解

    路由+视图 我们之前了解了路由系统是由带参数的装饰器完成的. 路由本质:装饰器和闭包实现的. 路由设置的两种方式 来看个例子. @app.route('/index') def index(): re ...

  8. tomcat启动startup.bat一闪而过

    编辑startup.bat,在文本最后添加PAUSE,保存后打开startup.bat,此时窗口会暂停,并出现错误信息,然后按照错误提示纠正即可!

  9. Map存储容量及内存占用测试

    Integer a = 1; long start = 0; long end = 0; // 先垃圾回收 System.gc(); start = Runtime.getRuntime().free ...

  10. Java集合类总结 (一)

    集合类中的基本接口 集合类中最基础的接口是Collection: public interface Collection<E> { boolean add(E element); Iter ...