初次接触CDQ分治,感觉真的挺厉害的。整体思路即分而治之,再用之前处理出来的答案统计之后的答案。

大概流程是(对于区间 l ~ r):

1.处理 l ~mid, mid + 1 ~ r 的答案;

2.分别排序规整;

3.计算 l ~ mid 中每一个数对 mid + 1 ~ r 中的答案的贡献, 累加;

4.得到区间l ~ r的答案。

CDQ分治我一共也才做了两道题目, 就一起整理在这里了。大体都差不多,CDQ+树状数组分别维护两个维度。

1.三维偏序

#include <bits/stdc++.h>
using namespace std;
#define maxn 3000000
#define lowbit(x) x &(-x)
int n, k, tot, ans[maxn], c[maxn];
struct node
{
int a, b, c, ans, cnt;
}num[maxn], a[maxn]; int read()
{
int x = , k = ;
char c;
c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} bool cmp(node a, node b)
{
if(a.a != b.a) return a.a < b.a;
if(a.b != b.b) return a.b < b.b;
return a.c < b.c;
} bool cmp2(node a, node b)
{
if(a.b != b.b) return a.b < b.b;
return a.c < b.c;
} void Update(int x, int v)
{
for(int i = x; i <= k; i += lowbit(i))
c[i] += v;
} int Query(int x)
{
int ans = ;
for(int i = x; i; i -= lowbit(i))
ans += c[i];
return ans;
} void cdq(int l, int r)
{
int mid = (l + r) >> ;
if(r - l >= ) cdq(l, mid), cdq(mid + , r);
if(r == l) return;
sort(num + l, num + mid + , cmp2);
sort(num + mid + , num + r + , cmp2);
int i = l, j = mid + ;
while(i <= mid && j <= r)
{
if(num[i].b <= num[j].b) Update(num[i].c, num[i].cnt), i ++;
else num[j].ans += Query(num[j].c), j ++;
}
while(i <= mid) Update(num[i].c, num[i].cnt), i ++;
while(j <= r) num[j].ans += Query(num[j].c), j ++;
for(int i = l; i <= mid; i ++) Update(num[i].c, -num[i].cnt);
} int main()
{
n = read(), k = read();
for(int i = ; i <= n; i ++)
a[i].a = read(), a[i].b = read(), a[i].c = read();
sort(a + , a + + n, cmp);
for(int i = ; i <= n;)
{
int j = ;
while(i + j <= n && a[i].a == a[i + j].a && a[i].b == a[i + j].b && a[i].c == a[i + j].c) j ++;
num[++ tot] = a[i];
num[tot].cnt = j;
i += j;
}
cdq(, tot);
for(int i = ; i <= tot; i ++) ans[num[i].ans + num[i].cnt - ] += num[i].cnt;
for(int i = ; i < n; i ++) printf("%d\n", ans[i]);
return ;
}

2.动态逆序对

#include <bits/stdc++.h>
using namespace std;
#define maxn 2000000
#define ll long long
#define lowbit(x) x & (-x)
int n, m, timer, a[maxn], b[maxn], d[maxn], t[maxn];
ll ans[maxn], c[maxn];
struct node
{
int t, num, pl;
ll ans;
}w[maxn]; int read()
{
int x = , k = ;
char c;
c = getchar();
while(c < '' || c > '') { if(c == '-') k = -; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * k;
} bool cmp(node a, node b)
{
if(a.t != b.t) return a.t < b.t;
else return a.pl < b.pl;
} bool cmp2(node a, node b)
{
return a.pl < b.pl;
} bool cmp3(node a, node b)
{
return a.pl > b.pl;
} void add(int x, int num)
{
for(int i = x; i <= n; i += lowbit(i))
c[i] += num;
} ll query(int x)
{
ll ans = ;
for(int i = x; i; i -= lowbit(i))
ans += c[i];
return ans;
} void CDQ(int l, int r)//位置在我之前,num>我的
{
int mid = (l + r) >> ;
if(r - l >= ) CDQ(l, mid), CDQ(mid + , r);
if(l == r) return;
sort(w + l, w + + mid, cmp2);
sort(w + mid + , w + r + , cmp2);
int i = l, j = mid + ;
while(i <= mid && j <= r)
{
if(w[i].pl < w[j].pl) add(w[i].num, ), i ++;
else w[j].ans += (query(n) - query(w[j].num)), j ++;
}
while(i <= mid) add(w[i].num, ), i ++;
while(j <= r) w[j].ans += (query(n) - query(w[j].num)), j ++;
for(int i = l; i <= mid; i ++)
add(w[i].num, -);
} void CDQ2(int l, int r)//位置在我之后,num<我的
{
int mid = (l + r) >> ;
if(r - l >= ) CDQ2(l, mid), CDQ2(mid + , r);
if(l == r) return;
sort(w + l, w + + mid, cmp3);
sort(w + mid + , w + r + , cmp3);
int i = l, j = mid + ;
while(i <= mid && j <= r)
{
if(w[i].pl > w[j].pl) add(w[i].num, ), i ++;
else w[j].ans += (query(w[j].num)), j ++;
}
while(i <= mid) add(w[i].num, ), i ++;
while(j <= r) w[j].ans += (query(w[j].num)), j ++;
for(int i = l; i <= mid; i ++)
add(w[i].num, -);
} int main()
{
n = read(), m = read();
for(int i = ; i <= n; i ++)
{
a[i] = read();
b[a[i]] = i;
}
timer = m;
for(int i = ; i <= m; i ++)
{
d[i] = read();
t[b[d[i]]] = timer --;
}
for(int i = ; i <= n; i ++) w[i].t = t[i], w[i].num = a[i], w[i].pl = i;
sort(w + , w + + n, cmp);
CDQ(, n);
for(int i = ; i <= n; i ++) ans[w[i].t] += w[i].ans;
for(int i = ; i <= n; i ++) w[i].t = t[i], w[i].num = a[i], w[i].pl = i, w[i].ans = ;
sort(w + , w + + n, cmp);
memset(c, , sizeof(c));
CDQ2(, n);
for(int i = ; i <= n; i ++) ans[w[i].t] += w[i].ans;
for(int i = ; i <= m; i ++) ans[i] += ans[i - ];
for(int i = m; i >= ; i --) printf("%lld\n", ans[i]);
return ;
}

【算法】CDQ分治 -- 三维偏序 & 动态逆序对的更多相关文章

  1. cdq分治·三维偏序问题

    转载自FlashHu大佬的博客CDQ分治总结(CDQ,树状数组,归并排序),在讲述部分有部分删改,用了自己的代码 CDQ分治的思想 CDQ分治是基于时间的离线分治算法.这一类分治有一个重要的思想——用 ...

  2. BZOJ 3262: 陌上花开 [CDQ分治 三维偏序]

    Description 有n朵花,每朵花有三个属性:花形(s).颜色(c).气味(m),又三个整数表示.现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量.定义一朵花A比另一朵花B要美丽,当 ...

  3. 洛谷P3810 陌上花开 CDQ分治(三维偏序)

    好,这是一道三维偏序的模板题 当然没那么简单..... 首先谴责洛谷一下:可怜的陌上花开的题面被无情的消灭了: 这么好听的名字#(滑稽) 那么我们看了题面后就发现:这就是一个三维偏序.只不过ans不加 ...

  4. NEUOJ 1702:撩妹全靠魅力值(CDQ分治三维偏序)

    http://acm.neu.edu.cn/hustoj/problem.php?id=1702 思路:三维偏序模板题,用CDQ分治+树状数组或者树套树.对于三元组(x,y,z),先对x进行排序,然后 ...

  5. BZOJ 2244: [SDOI2011]拦截导弹 (CDQ分治 三维偏序 DP)

    题意 略- 分析 就是求最长不上升子序列,坐标取一下反就是求最长不下降子序列,比较大小是二维(h,v)(h,v)(h,v)的比较.我们不看概率,先看第一问怎么求最长不降子序列.设f[i]f[i]f[i ...

  6. CDQ分治 三维偏序

    这应该是一道CDQ分治的入门题目 我们知道,二维度的偏序问题直接通过,树状数组就可以实现了,但是三维如何实现呢? 我记得以前了解过一个小故事,应该就是分治的. 一个皇帝,想给部下分配任务,但是部下太多 ...

  7. BZOJ.1935.[SHOI2007]Tree园丁的烦恼(CDQ分治 三维偏序)

    题目链接 矩形查询可以拆成四个点的前缀和查询(树套树显然 但是空间不够) 每个操作表示为(t,x,y),t默认有序,对x分治,y用树状数组维护 初始赋值需要靠修改操作实现. //119964kb 43 ...

  8. BZOJ.3262.陌上花开([模板]CDQ分治 三维偏序)

    题目链接 BZOJ3262 洛谷P3810 /* 5904kb 872ms 对于相邻x,y,z相同的元素要进行去重,并记录次数算入贡献(它们之间产生的答案是一样的,但不去重会..) */ #inclu ...

  9. BZOJ - 1935 / 1176 cdq分治 三维偏序

    题意:给定n*m的网格,且给出n个(x,y)表示该网格已被占有,q次询问(x1,y1)到(x2,y2)的网格中有多少个被占有,n,m范围1e7,q范围5e5 cdq按x轴排序,树状数组维护y轴 #in ...

随机推荐

  1. Xcode升到7.1插件失效解决方法

    Mac前段时间下载了新的OS系统与Xcode 7.1,然而在使用Xcode 7.1时,发现插件不能用了,瞬间木有爱了,正好交流群里有人问到了插件失效的问题,经过各路大神的神通最终用下面这种方法完美解决 ...

  2. koa2 mongdb 做后端接口的小demo

    现在前端全栈里面有一种技术栈比较火 前端使用 vue 或者react 后端使用 koa2 mysql数据库 或者mongdb做数据储存 但是基本这样的全栈教程 都要收费 收费就收费吧 但是 有没有遇到 ...

  3. elasticsearch搜索引擎搭建

    在该路径下,运行elasticsearch.bat该命令,后面访问127.0.0.1:9200 出现如下界面说明启动成功 elasticsearch-head操作elasticsearch的图形界面, ...

  4. is和==,编码补充

    一,is和==的区别: 1, 通过一个ID()可以查看到一个变量表示的值在内存中的地址.    s = 'alex' print(id(s)) # 4326667072 s = "alex& ...

  5. 001---C/S架构

    C/S 架构介绍 什么是C/S架构 C:client,客户端 S:server,服务端 实现客户端和服务端之间的网络通信 什么是网络 人与人之间交流是通过语言,才能彼此理解对方的意思.但是地球上有多个 ...

  6. UVA10474 Where is the Marble?【排序】

    参考:https://blog.csdn.net/q547550831/article/details/51326321 #include <iostream> #include < ...

  7. 引用外部静态库(.a文件)时或打包.a时,Category方法无法调用。崩溃

    我的这个是MJRefresh,学习打.a包Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: ...

  8. js学习日记-隐式转换相关的坑及知识

    隐式转换比较是js中绕不过去的坎,就算有几年经验的工程师也很有可能对这块知识不够熟悉.就算你知道使用===比较从而避免踩坑,但是团队其它成员不一定知道有这样或那样的坑,有后端语言经验的人常常会形成一个 ...

  9. Python面试315题

    感谢老男孩的武沛齐老师辛苦整理和分享,本文是转自他的博客. 第一部分 Python基础篇(80题) 为什么学习Python? 通过什么途径学习的Python? Python和Java.PHP.C.C# ...

  10. Python全栈 MongoDB 数据库(聚合、二进制、GridFS、pymongo模块)

    断网了2天  今天补上     聚合操作: 对文档的信息进行整理统计的操作 返回:统计后的文档集合 db.collection.aggregate() 功能:聚合函数,完成聚合操作 参数:聚合条件,配 ...