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 ...
随机推荐
- 关于FFT分析音频的学习
本文部分知识从以下文章学习: https://zhuanlan.zhihu.com/p/19763358 傅里叶变换的知识 https://www.cnblogs.com/RabbitHu/p/FFT ...
- Linux基础管道管理
一.I/O重定向 标准输入,标准输出,标准错误 file descriptors (FD, 文件描述符或Process I/O channels); 进程使用文件描述符来管理打开的文件 [root@l ...
- CodeGlance右侧窗口缩略图消失不见
说明下问题,idea中的CodeGlance插件会在右侧显示缩略图,可以快速定位代码.今天遇到个问题升级了插件后右侧窗口消失.经过卸载插件,重启,reset一系列操作后还是没能恢复. 能去搜索引擎搜索 ...
- JAVA基础知识(四):final关键字
final关键字可以用于成员变量.本地变量.方法以及类. 2. final成员变量必须在声明的时候初始化或者在构造器中初始化,否则就会报编译错误. 3. 你不能够对final变量再次赋值. 4. 本地 ...
- android ——活动的生命周期
在其生命周期内,activity在运行.暂停和停止三种可能的状态间进行转换,不同状态之间互相转换的时候的调用不同的方法,重写这些方法就能在活动切换,被销毁时保存或传输数据,在被启动.被切换出来时接收数 ...
- ZooKeeper系列(二)—— Zookeeper 单机环境和集群环境搭建
一.单机环境搭建 1.1 下载 下载对应版本 Zookeeper,这里我下载的版本 3.4.14.官方下载地址:https://archive.apache.org/dist/zookeeper/ # ...
- c#自定义控件中的事件处理
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; u ...
- 神经网络优化算法:Dropout、梯度消失/爆炸、Adam优化算法,一篇就够了!
1. 训练误差和泛化误差 机器学习模型在训练数据集和测试数据集上的表现.如果你改变过实验中的模型结构或者超参数,你也许发现了:当模型在训练数据集上更准确时,它在测试数据集上却不⼀定更准确.这是为什么呢 ...
- 行车记+翻车记:.NET Core 新车改造,C# 节能降耗,docker swarm 重回赛道
非常抱歉,10:00~10:30 左右博客站点出现故障,给您带来麻烦了,请您谅解. 故障原因与博文中谈到的部署变更有关,但背后的问题变得非常复杂,复杂到我们都在怀疑与阿里云服务器 CPU 特性有关. ...
- ip地址、域名、DNS、URL的区别与联系
IP:每个连接到Internet上的主机都会分配一个IP地址,此ip是该计算机在互联网上的逻辑地址的唯一标识,计算机之间的访问就是通过IP地址来进行的.写法:十进制的形式,用“.”分开,叫做“点分十进 ...