/* CDQ分治的对象是时间。
即对于一个时间段[L, R],我们取mid = (L + R) / 2。
分治的每层只考虑mid之前的修改对mid之后的查询的贡献,然后递归到[L,mid],(mid,R]。
显然,CDQ分治是一种离线算法,我们需要将所有的修改/查询存下来,一起进行操作。
同时,CDQ分治还需要满足:操作之间相互独立,即一个操作的存在不会影响到另一个操作的存在。
经典入门题 单点修改 矩形查询
如果此题矩形小一点的话 可以使用树状数组套线段树
但是矩形过大时就不适用了
这里可以将一个询问拆成四个前缀和查询,然后和修改操作一起 做cdq分治
*/
#include<bits/stdc++.h>
#define LL long long using namespace std;
const int N = 2e6 + 1; int tr[N],W;
int lowbit(int x){return x & (-x);}
void up(int pos,int v){
for(;pos <= W;pos += lowbit(pos)) tr[pos] += v;
}
int getsum(int pos){
int ans = 0;
for(;pos;pos -= lowbit(pos)) ans += tr[pos];
return ans;
}
struct Q{
int x, y, type, q, v, order;
Q(){};
Q(int x,int y,int type, int q,int v,int order):x(x),y(y),type(type),q(q),v(v),order(order){};
bool operator<(const Q&rhs)const{
return x < rhs.x;
}
}qr[N],tmp[N];
int ans[N];
void cdq(int l,int r){
if(l == r) return ;
int mid = l + r >> 1;
int p1 = l,p2 = mid + 1;
/// 首先将mid之前的操作 全部放到mid左边 mid之后的操作全部放到右边,保证了按时间分治,并且左右都是x递增的
for(int i = l;i <= r;i++){
if(qr[i].order <= mid) tmp[p1++] = qr[i];
else tmp[p2++] = qr[i];
}
for(int i = l;i <= r;i++) qr[i] = tmp[i];
int j = l;
///计算完mid时间轴左边的修改对右边查询的贡献,恢复修改
for(int i = mid + 1;i <= r;i++){
if(qr[i].type == 2) {
for(; j <= mid && qr[j].x <= qr[i].x; j++){
if(qr[j].type == 1) up(qr[j].y,qr[j].v);
}
ans[qr[i].q] += qr[i].v * getsum(qr[i].y);
}
}
for(int i = l;i < j;i++) if(qr[i].type == 1) up(qr[i].y, -qr[i].v);
///进行递归分治
cdq(l, mid);cdq(mid + 1, r);
}
int main()
{ int op, a, b, c, d, id = 0, tot = 0;
while(scanf("%d", &op) && op != 3){
if(op == 0)
scanf("%d", &W);
else if(op == 1){
scanf("%d%d%d", &a, &b, &c);
qr[++id] = Q(a, b, 1, 0, c, id);
}
else{
++tot;
scanf("%d%d%d%d", &a, &b, &c, &d);
qr[++id] = Q(a - 1, b - 1, 2, tot, 1, id);
qr[++id] = Q(c, d, 2, tot, 1, id);
qr[++id] = Q(a - 1, d, 2, tot, -1, id);
qr[++id] = Q(c, b - 1, 2, tot, -1, id);
}
}
sort(qr + 1, qr + id + 1);
cdq(1, id);
for(int i = 1; i <= tot; i++)
printf("%d\n", ans[i]);
return 0;
}

http://codeforces.com/gym/101485/attachments
求出多少对(i,j) 满足i < j 且a[j] < a[i] 且 b[j] < b[i]
做法 第一维分治 第二维树状数组 时间复杂度为O(nlognlogn) 空间复杂度O(n)
解决二维偏序问题 其他做法可能空间复杂度为过高 #include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#define LL long long
using namespace std;
#define ms(dp,x) memset(dp,x,sizeof dp) const int N = 2e5 + 10;
LL ans;
int n;
int tr[N];
int vis[N];
struct Q{
int id,a,b,c;
Q(){};
}q[N]; int lowbit(int x){return x &(-x);}
void up(int pos,int v){
for(;pos <= n;pos += lowbit(pos)) tr[pos] += v;
}
int getsum(int pos){
int ans = 0;
for(;pos;pos -= lowbit(pos)) ans += tr[pos];
return ans;
}
bool cmpx(Q x,Q y){return x.b < y.b;}
bool cmprx(Q x,Q y){return x.id < y.id;}
void cdq(int l,int r){
if(l == r) return ;
int mid = l + r >> 1;
cdq(l,mid);
sort(q + l,q + mid + 1, cmpx);
sort(q + mid + 1,q + r + 1, cmpx);
int i = l;
LL tmp = 0;
for(int j = mid + 1;j <= r;j++){
while(i <= mid && q[i].b < q[j].b) {
up(q[i++].c,1);
}
tmp += getsum(q[j].c - 1);
}
ans += tmp;
i = l;
for(int j = mid + 1;j <= r;j++){
while(i <= mid && q[i].b < q[j].b) {
up(q[i++].c,-1);
}
}
sort(q + mid + 1,q + r + 1, cmprx);
cdq(mid + 1,r);
}
int main()
{
int x;
while(scanf("%d",&n)==1){ for(int i = 1;i <= n;i++) {
scanf("%d",&q[i].a);
vis[q[i].a] = i;
q[i].id = i;
}
for(int i = 1;i <= n;i++) {
scanf("%d",&x);
q[vis[x]].b = i;
}
for(int i = 1;i <= n;i++) {
scanf("%d",&x);
q[vis[x]].c = i;
}
memset(tr, 0, sizeof tr);
ans = 0;
cdq(1,n);
printf("%lld\n",ans);
}
return 0;
}
/*
8
1 4 8 3 5 7 2 6
6 4 8 3 5 2 7 1
6 4 8 3 5 2 7 1
*/

cdq分治入门学习 cogs 1752 Mokia nwerc 2015-2016 G 二维偏序的更多相关文章

  1. 【教程】简易CDQ分治教程&学习笔记

    前言 辣鸡蒟蒻__stdcall终于会CDQ分治啦!       CDQ分治是我们处理各类问题的重要武器.它的优势在于可以顶替复杂的高级数据结构,而且常数比较小:缺点在于必须离线操作. CDQ分治的基 ...

  2. [偏序关系与CDQ分治]【学习笔记】

    组合数学真是太棒了 $CDQ$真是太棒了(雾 参考资料: 1.<组合数学> 2.论文 课件 很容易查到 3.sro __stdcall 偏序关系 关系: 集合$X$上的关系是$X$与$X$ ...

  3. CDQ分治入门 + 例题 Arnooks's Defensive Line [Uva live 5871]

    CDQ分治入门 简介 CDQ分治是一种特别的分治方法,它由CDQ(陈丹琦)神犇于09国家集训队作业中首次提出,因此得名.CDQ分治属于分治的一种.它一般只能处理非强制在线的问题,除此之外这个算法作为某 ...

  4. CDQ分治(学习笔记)

    离线算法——CDQ分治 CDQ (SHY)显然是一个人的名字,陈丹琪(MM)(NOI2008金牌女选手). 从归并开始(这里并没有从逆序对开始,是想直接引入分治思想,而不是引入处理对象) 一个很简单的 ...

  5. CDQ分治入门

    前言 \(CDQ\)分治是一个神奇的算法. 它有着广泛的用途,甚至在某些题目中还能取代\(KD-Tree\).树套树等恶心的数据结构成为正解,而且常数还小得多. 不过它也有一定的缺点,如必须离线操作, ...

  6. caioj1097: [视频]树状数组1(快速求和计算) cdq分治入门

    这题虽然是个树状数组,但是也可以用cdq分治做啊~~,这个就是一个浅显的二维偏序的应用? cdq分治和普通的分治有什么区别? 举个栗子:有4个小朋友,你请他们吃饭,假如你分治搞,就会分成很多子问题—— ...

  7. 【学术篇】bzoj3262 陌上花开. cdq分治入门

    花儿们已经很累了-- 无论是花形.颜色.还是气味, 都不是为了给人们摆出来欣赏的, 更不是为了当做出题的素材的, 她们并不想自己这些属性被没有生命的数字量化, 并不想和其它的花攀比, 并无意分出个三六 ...

  8. COGS 577 蝗灾 [CDQ分治入门题]

    题目链接 昨天mhr神犇,讲分治时的CDQ分治的入门题. 题意: 你又一个w*w正方形的田地. 初始时没有蝗虫. 给你两个操作: 1. 1 x y z: (x,y)这个位置多了z只蝗虫. 2. 2 x ...

  9. cdq分治入门and持续学习orz

    感觉cdq分治是一个很有趣的算法 能将很多需要套数据结构的题通过离线来做 目前的一些微小的理解 在一般情况下 就像求三维偏序xyz 就可以先对x排序 然后分治 1 cdq_x(L,M) ; 2 提取出 ...

随机推荐

  1. yum方式安装及配置最新的mysql5.7

    1.删除旧版本的MySQL rpm -qa|grep -i mysql 用命令yum -y remove mysql 2.下载新版安装源 下载mysql的repo源 这个安装的mysql5.7.20 ...

  2. C# FTP上传文件时出现"应 PASV 命令的请求,服务器返回了一个与 FTP 连接地址不同的地址。"的错误

    FTP上传文件时出现"应 PASV 命令的请求,服务器返回了一个与 FTP 连接地址不同的地址."的错误 解决方法是在原代码上增加这句话 reqFTP.UsePassive = f ...

  3. MVC模型与MTV模型

    MVC模型: MVC(Model View Controller 模型-视图-控制器)是一种Web架构的模式,它把业务逻辑.模型数据.用户界面分离开来,让开发者将数据与表现解耦,前端工程师可以只改页面 ...

  4. Nginx一直报504超时,配置相关参数好了

    相关参数:large_client_header_buffers 4 16k;client_max_body_size 30m;client_body_buffer_size 128k;proxy_c ...

  5. Java线程和多线程(十)——TimerTask

    Java中的java.util.Timer是一个工具类,可以用于调度一个线程在将来的某一个时刻执行特定的任务.Java Timer类可以将一个任务定时执行一次,或者是以后以每隔一定的时间间隔来触发一次 ...

  6. Messy Code in Windows Server 2008 R2 English Edition

          We always use Windows Server 2008 R2 English operation system. And it doesn't have any problem ...

  7. CSS里一个奇怪的属性

    事情是这样的,在一个手机界面的制作中,我发现按钮点击后总会出现一个边框,于是开始搜索解决方案.搜到的解决方案是这样的. a:focus,input:focus{ -webkit-tap-highlig ...

  8. 「赛后补题」HBCPC2018题目代码与思路简析

    这次比赛(2018年第二届河北省大学生程序设计竞赛)虽然没有打,但是题目还是要写的.未完成的题目(还差比较硬核的四题)和思路分析会陆续更新完. Problem A 2011 Mex Query /* ...

  9. MySQL☞between ... and ...

    between  初值  and  终值:求出该列列值在初值和终值之间所有的数据 格式如下: select 列名/* from 表名 where 列名 between 初值 and 终值 如下图:

  10. PL/SQL查看表结构

    SET LONG 99999;SET LINESIZE 140 PAGESIZE 1000;SELECT DBMS_METADATA.GET_DDL('&OBJECT_TYPE','& ...