/* 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. Flask之endpoint错误View function mapping is overwriting an existing endpoint function: ***

    最近在学习Flask, 其中遇到了一个错误, 发现这个问题和Flask, 路由有关系, 所以就记了下来 错误代码: from flask import Flask, render_template, ...

  2. 廖老师的Python教程——安装Python

    因为Python是跨平台的,它可以运行在Windows.Mac和各种Linux/Unix系统上.在Windows上写Python程序,放到Linux上也是能够运行的. 要开始学习Python编程,首先 ...

  3. python 复习函数 装饰器

    # 函数 —— 2天 # 函数的定义和调用 # def 函数名(形参): #函数体 #return 返回值 #调用 函数名(实参) # 站在形参的角度上 : 位置参数,*args,默认参数(陷阱),* ...

  4. DLX算法一览

    目录: 1 X思想的了解. 链表的递归与回溯. 具体操作. 优化. 一些应用与应用中的再次优化(例题). 练手题 X思想的了解. 首先了解DLX是什么? DLX是一种多元未饱和型指令集结构,DLX 代 ...

  5. c语言中 *p++ 和 (*p)++ 和 *(p++) 和 *(++p) 和++(*p)和 *(p--)和 *(--p)有什么区别?

    *p++是指下一个地址; (*p)++是指将*p所指的数据的值加一; /******************解释**********************/ ->C编译器认为*和++是同优先级 ...

  6. Java基础——内部类

    一.什么是内部类 将一个类定义在另一个类里面或者一个方法里面,这样的类称为内部类 内部类所在的类在编译成功后,会出现这样两个class文件:OuterClass.class和OuterClass$In ...

  7. L009文件属性知识详解小节

    本堂课分为5部分内容 1.linux下重要目录详解 2.PATH变量路径内容 3.linux系统中文件类型介绍 4.linux系统中文件属性详细介绍 5.linux系统文件属性inode与block知 ...

  8. web开发微信文章目录

    Web开发微信文章目录 2015-12-13 Web开发 本文是Web开发微信的文章目录.通过目录查看文章编号,回复文章编号就能查看文章全文. 回复编号查看全文,搜索分类名可以获得该分类下的文章.   ...

  9. ASP.NET MVC 使用jquery.form.js 异步上传 在IE下返回值被变为下载的解决办法

    错误记录: <script type="text/javascript"> $(function () { $(document).off("ajaxSend ...

  10. Ngix配置,让所有请求指向同一个文件

    统一入口使所有请求在同一个文件先验证处理,Ngix添加如下代码: location / { try_files '' /index.php; }