CodeChef - QRECT Rectangle Query CDQ分治
题解:现在需要维护的每次的询问矩形和前面插入的所有矩形有公共部分的个数。 我们试着直接去维护这个东西, 发现可能的情况太多,不好维护,所以我们维护每次询问的时候在当前矩阵个数下,有多少个矩阵是一定在外面的。对于一个矩阵来说, 我们只需要统计到目前位置, 多少个矩形的下底线 在询问矩形的上底线之上, 这样我们就减去了在询问矩形上方的不重合矩形。 然后我们对矩形的左右下也一样维护这个信息。对于这个操作我们可以用4个树状数组直接去维护这个信息。每个数状数组记录一下每条底线出现的位置。
维护完这个东西之后,我们发现如果一个矩形在询问矩形的左上方, 他会被减去2次,这样就多减了, 我们需要把左上角的矩形个数再加回去。 我们需要 对每个询问矩形来说, 维护出有多少个插入矩形的右下角的端点是在询问矩形的左上角的端点的左上角, 对于这个问题就变成了一个2维偏序问题,我们用cdq去维护这个信息。当然还有其他3个角落,我们也需要对那些角度做一样的操作。最后我们就可以得到答案了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL mod = (int)1e9+;
const int N = 2e5 + ;
struct Node{
int x1, y1, x2, y2, op, id;
}A[N], B[N];
int xsz, ysz;
int x[N], y[N];
int tmp[N];
int ans[N];
char s[];
struct bit_tree{
int tree[N], tot;
void add(int x, int v){
for(int i = x; i < N; i += i & (-i)){
tree[i] += v;
}
tot += v;
}
int query(int x){
int ret = ;
for(int i = x; i > ; i -= i & (-i)){
ret += tree[i];
}
return ret;
}
void Clear(){
tot = ;
memset(tree, , sizeof(tree));
}
}bit[];
bool cmp1(Node & a, Node & b){
int aop = abs(a.op), bop = abs(b.op);
int ax, bx;
if(aop) ax = a.x2;
else ax = a.x1;
if(bop) bx = b.x2;
else bx = b.x1;
if(ax != bx) return ax < bx;
return aop < bop;
}
bool cmp2(Node & a, Node & b){
int aop = abs(a.op), bop = abs(b.op);
int ax, bx;
if(!aop) ax = a.x2;
else ax = a.x1;
if(!bop) bx = b.x2;
else bx = b.x1;
if(ax != bx) return ax > bx;
return aop < bop;
}
void cdq(int l, int r){
if(l >= r) return ;
int mid = l+r >> ;
cdq(l, mid);
cdq(mid+, r);
int top = ;
for(int i = l; i <= mid; i++)
if(A[i].op) B[++top] = A[i];
for(int i = mid+; i <= r; i++)
if(!A[i].op) B[++top] = A[i];
sort(B+, B++top, cmp1);
for(int i = ; i <= top; i++){
if(B[i].op) {
bit[].add(B[i].y1, B[i].op);
bit[].add(B[i].y2, B[i].op);
}
else {
ans[B[i].id] += bit[].tot - bit[].query(B[i].y2);
ans[B[i].id] += bit[].query(B[i].y1-);
}
}
for(int i = ; i <= top; i++){
if(B[i].op) {
bit[].add(B[i].y1, -B[i].op);
bit[].add(B[i].y2, -B[i].op);
}
}
sort(B+, B++top, cmp2);
for(int i = ; i <= top; i++){
if(B[i].op) {
bit[].add(B[i].y1, B[i].op);
bit[].add(B[i].y2, B[i].op);
}
else {
ans[B[i].id] += bit[].tot - bit[].query(B[i].y2);
ans[B[i].id] += bit[].query(B[i].y1-);
}
}
for(int i = ; i <= top; i++){
if(B[i].op) {
bit[].add(B[i].y1, -B[i].op);
bit[].add(B[i].y2, -B[i].op);
}
}
}
int main(){
int n;
scanf("%d", &n);
int t = , tt = , num = , z;
for(int i = ; i <= n; ++i){
scanf("%s", s);
if(s[] == 'I'){
num++;
scanf("%d%d%d%d", &A[i].x1, &A[i].y1, &A[i].x2, &A[i].y2);
x[++xsz] = A[i].x1; x[++xsz] = A[i].x2;
y[++ysz] = A[i].y1; y[++ysz] = A[i].y2;
A[i].op = ;
tmp[++t] = i;
}
else if(s[] == 'D'){
num--;
scanf("%d", &z);
A[i] = A[tmp[z]];
A[i].op = -;
}
else {
++tt;
scanf("%d%d%d%d", &A[i].x1, &A[i].y1, &A[i].x2, &A[i].y2);
x[++xsz] = A[i].x1; x[++xsz] = A[i].x2;
y[++ysz] = A[i].y1; y[++ysz] = A[i].y2;
A[i].op = ;A[i].id = tt;
ans[tt] = num;
}
}
sort(x+, x+xsz+); sort(y+, y+ysz+);
xsz = unique(x+, x++xsz) - x - ;
ysz = unique(y+, y++ysz) - y - ;
for(int i = ; i <= n; i++){
A[i].x1 = lower_bound(x+, x++xsz, A[i].x1) - x;
A[i].x2 = lower_bound(x+, x++xsz, A[i].x2) - x;
A[i].y1 = lower_bound(y+, y++ysz, A[i].y1) - y;
A[i].y2 = lower_bound(y+, y++ysz, A[i].y2) - y;
if(A[i].op){
bit[].add(A[i].x1, A[i].op);
bit[].add(A[i].x2, A[i].op);
bit[].add(A[i].y1, A[i].op);
bit[].add(A[i].y2, A[i].op);
}
else {
num = ans[A[i].id];
ans[A[i].id] -= num - bit[].query(A[i].x2);
ans[A[i].id] -= bit[].query(A[i].x1-);
ans[A[i].id] -= num - bit[].query(A[i].y2);
ans[A[i].id] -= bit[].query(A[i].y1-);
}
}
for(int i = ; i < ; i++) bit[i].Clear();
cdq(, n);
for(int i = ; i <= tt; i++)
printf("%d\n", ans[i]);
return ;
}
CodeChef - QRECT Rectangle Query CDQ分治的更多相关文章
- Codechef SEP14 QRECT cdq分治+线段树
题意 支持删除矩阵.插入矩阵.查询当前矩阵与之前有多少个矩阵相交 算相交的时候容斥一下:相交矩形数 = 总矩形数-X轴投影不相交的矩形数-Y轴投影不相交的矩形数-XY轴投影下都不相交的矩形数 最后一项 ...
- 算法笔记--CDQ分治 && 整体二分
参考:https://www.luogu.org/blog/Owencodeisking/post-xue-xi-bi-ji-cdq-fen-zhi-hu-zheng-ti-er-fen 前置技能:树 ...
- 【教程】简易CDQ分治教程&学习笔记
前言 辣鸡蒟蒻__stdcall终于会CDQ分治啦! CDQ分治是我们处理各类问题的重要武器.它的优势在于可以顶替复杂的高级数据结构,而且常数比较小:缺点在于必须离线操作. CDQ分治的基 ...
- BZOJ 2683 简单题 ——CDQ分治
[题目分析] 感觉CDQ分治和整体二分有着很本质的区别. 为什么还有许多人把他们放在一起,也许是因为代码很像吧. CDQ分治最重要的是加入了时间对答案的影响,x,y,t三个条件. 排序解决了x ,分治 ...
- 初识CDQ分治
[BZOJ 1176:单点修改,查询子矩阵和]: 1176: [Balkan2007]Mokia Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 200 ...
- BZOJ4170 极光(CDQ分治 或 树套树)
传送门 BZOJ上的题目没有题面-- [样例输入] 3 5 2 4 3 Query 2 2 Modify 1 3 Query 2 2 Modify 1 2 Query 1 1 [样例输出] 2 3 3 ...
- BZOJ2683 简单题(CDQ分治)
传送门 之前听别人说CDQ分治不难学,今天才知道果真如此.之前一直为自己想不到CDQ的方法二很不爽,今天终于是想出来了一道了,太弱-- cdq分治主要就是把整段区间分成两半,然后用左区间的值去更新右区 ...
- 【BZOJ-3262】陌上花开 CDQ分治(3维偏序)
3262: 陌上花开 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1439 Solved: 648[Submit][Status][Discuss ...
- 【BZOJ-1176&2683】Mokia&简单题 CDQ分治
1176: [Balkan2007]Mokia Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 1854 Solved: 821[Submit][St ...
随机推荐
- SQL Server 插入数据时自增长列如何指定数值
SQL Server 表在导入数据时,有时需要将自增长列指定数值,来保证导入前后的数据完全一致,如何实现? SQL Server 提供了方法: SET IDENTITY_INSERT,允许将显式值插入 ...
- Qtech 暑假未讲到的算法(不完全)
一.数据结构: 优先队列.堆.RMQ问题(区间最值问题,可以用线段树解决,还有一个Sparse-Table算法).排序二叉树.划分树.归并树..... 字符串处理: KMP.字典树.后 ...
- 数据结构之堆栈java版
import java.lang.reflect.Array; /* 具体原理在c++版已经说的很清楚,这里不再赘述, 就提一点:java的泛型具有边界效应,一旦离开作用域立马被替换为object类型 ...
- SpringBoot第二天
一,SpringBoot 整合 jsp 技术 1,创建项目 2,修改 pom 文件,添加坐标 <project xmlns="http://maven.apache.org/POM/4 ...
- 从零开发一款自己的小程序UI组件库(二)
写在前面:从零开发一款自己的小程序UI组件库(一) 上节我们讲到初始化组件库模板.模板文件概述.模板上传npm以及npm包文件下载至本地并运用到项目.这节我们继续,内容主要有基础UI组件库的搭建(bu ...
- 「求助」关于MacOS 适配不了SOIL的问题 以及我自己愚蠢的解决办法
我的环境 macOS High Sierra 10.13.6 (2018) 我的SOIL源是通过 终端 git clone https://github.com/DeVaukz/SOIL 直接从gay ...
- POI通用导出Excel数据(包括样式设计)
前言 前一段时间我写过通用的导入Excel,前几天也写了导出pdf格式的,还有我之前搞得导出Word,我在之前的博客也都介绍了导出和导入是一个道理,无非是一个获取一个是赋值.昨天有一位同仁看了我的Ex ...
- vi编辑器基础指令
vi -- 终端中的编辑器 visual interface ssh-- secure shell vim vi improved-----------------------------打开和新建文 ...
- 把Python项目打包成exe文件
我们很多时候,写好的程序需要打包成.exe文件才可以发给客户,那么今天我就来谈一谈,如何将一个写好的Python程序打包成exe文件! 首先,我们我们使用到的工具是python 3.7 和 Pyins ...
- JavaWeb零基础入门-01 基础概念说明
一.序言 从学校出来到实习,发现学校学的东西太过基础,难于直接运用于工作中.而且工作中,现在都以web开发为主,学校开了web开发相关课程.自己学的不够深入,所以本人自学JavaWeb开发,介于学习巩 ...