http://www.lydsy.com/JudgeOnline/problem.php?id=3295

题意:简单明了。

思路:终于好像有点明白CDQ分治处理三维偏序了。把删除操作看作是插入操作,那么可以按照插入的时间顺序看作是一维x,插入的数在原本序列的下标是一维y,插入的数本身是一维z。那么问题可以转化成每插入一个数(xx,yy,zz),求有多少个数(x,y,z)使得 x < xx,y < yy,z > zz 。一开始先对 x 进行排序,然后进行CDQ分治。这样可以干掉一维,保证随着时间递增。在分治的时候,通过标记判断那一个点属于左半区间还是右半区间,然后对 y 进行排序。如果在左半区间,那么它的 x 必定是小于 右半区间的,它所修改的结果会影响右半区间的查询,因此要去更新左半区间的元素。因为 y 是升序的,那么正着查询大于该点的 z 值的个数,就是查询可以满足 y < yy, z > zz 的条件的个数了。反着查询小于该点的 z 值的个数,即满足 y > yy, z < zz 的条件的个数。这样就可以找全插入一个数对整个数组产生的逆序对的个数了。

 #include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
#define N 100010
struct node {
int x, y, z, f;
node () {}
node (int x, int y, int z) : x(x), y(y), z(z) {}
} p[N], s[N]; int bit[N], gap, num[N], Hash[N];
LL ans[N]; bool cmpx(const node &a, const node &b) {
return a.x < b.x;
}
bool cmpy(const node &a, const node &b) {
if(a.y == b.y) return a.z < b.z;
return a.y < b.y;
} int lowbit(int x) { return x & (-x); } LL query(int x) {
LL ans = ;
while(x) { ans += bit[x]; x -= lowbit(x); }
return ans;
} void update(int x, int w) {
while(x <= gap) { bit[x] += w; x += lowbit(x); }
} void CDQ(int l, int r) {
if(l == r) return ;
int m = (l + r) >> , cnt = ;
CDQ(l, m); CDQ(m + , r);
for(int i = l; i <= m; i++) s[++cnt] = p[i], s[cnt].f = ; // 在左半部分
for(int i = m + ; i <= r; i++) s[++cnt] = p[i], s[cnt].f = ; // 在右半部分
sort(s + , s + + cnt, cmpy); // 根据y排序
for(int i = ; i <= cnt; i++) { // 正着扫
if(!s[i].f) update(s[i].z, ); // 左半部分对右半部分的查询有影响因此更新
else ans[s[i].x] += query(gap) - query(s[i].z); // 在[m,r]区间查询大于它的z的数量
}
for(int i = ; i <= cnt; i++) if(!s[i].f) update(s[i].z, -);
for(int i = cnt; i >= ; i--) { // 逆着扫
if(!s[i].f) update(s[i].z, );
else ans[s[i].x] += query(s[i].z); // 在[m,r]区间查询小于它的z的数量
}
for(int i = ; i <= cnt; i++) if(!s[i].f) update(s[i].z, -);
} int main() {
int n, m;
while(~scanf("%d%d", &n, &m)) {
int a, cnt = ;
gap = ;
for(int i = ; i <= n; i++) {
scanf("%d", &num[i]);
Hash[num[i]] = i;
p[i] = node(, i, num[i]);
if(num[i] > gap) gap = num[i];
}
for(int i = ; i <= m; i++) {
scanf("%d", &a);
p[Hash[a]].x = n - i + ;
}
for(int i = ; i <= n; i++)
if(p[i].x == ) p[i].x = ++cnt;
sort(p + , p + + n, cmpx);
memset(bit, , sizeof(bit));
CDQ(, n);
LL res = ;
for(int i = ; i <= n; i++) res += ans[i];
for(int i = n; i > n - m; i--) {
printf("%lld\n", res);
res -= ans[i];
}
}
return ;
}

BZOJ 3295:[Cqoi2011]动态逆序对(三维偏序 CDQ分治+树状数组)的更多相关文章

  1. BZOJ 3295 [CQOI2011]动态逆序对 (三维偏序CDQ+树状数组)

    题目大意: 题面传送门 还是一道三维偏序题 每次操作都可以看成这样一个三元组 $<x,w,t>$ ,操作的位置,权值,修改时间 一开始的序列看成n次插入操作 我们先求出不删除时的逆序对总数 ...

  2. BZOJ 3295: [Cqoi2011]动态逆序对

    3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3865  Solved: 1298[Submit][Sta ...

  3. Bzoj 3295: [Cqoi2011]动态逆序对 分块,树状数组,逆序对

    3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2886  Solved: 924[Submit][Stat ...

  4. 【刷题】BZOJ 3295 [Cqoi2011]动态逆序对

    Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计 ...

  5. BZOJ 3295: [Cqoi2011]动态逆序对 [CDQ分治]

    RT 传送门 首先可以看成倒着插入,求逆序对数 每个数分配时间(注意每个数都要一个时间)$t$,$x$位置,$y$数值 $CDQ(l,r)$时归并排序$x$ 然后用$[l,mid]$的加入更新$[mi ...

  6. bzoj 3295 [Cqoi2011]动态逆序对(cdq分治,BIT)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3295 [题意] n个元素依次删除m个元素,求删除元素之前序列有多少个逆序对. [思路] ...

  7. bzoj 3295: [Cqoi2011]动态逆序对(树套树 or CDQ分治)

    Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计 ...

  8. BZOJ 3295 [Cqoi2011]动态逆序对 ——CDQ分治

    时间.位置.数字为三个属性. 排序时间,CDQ位置,树状数组处理数字即可. #include <cstdio> #include <cstring> #include < ...

  9. 2018.07.01 BZOJ3295: [Cqoi2011]动态逆序对(带修主席树)

    3295: [Cqoi2011]动态逆序对 **Time Limit: 10 Sec Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j& ...

随机推荐

  1. 【 D3.js 入门系列 --- 6 】 如何使移动图表

    我的个人博客是: www.ourd3js.com csdn博客为: blog.csdn.net/lzhlzz 转载请注明出处,谢谢. [5.1]节中制作了一个比較完好的图表.但它是静态的.想做出它的动 ...

  2. 批量删除C和C++注释

    使用Python语言 ,实现批量删除C/C++类型注释1.目前支持去掉.h .hpp .c .cpp .java 这些以//或/**/为注释符的源文件 2.支持递归遍历目录 3.当前版本为Python ...

  3. symfony 数据库表生成实体、迁移数据库

    从数据库表生成实体 1. 由数据库生成模型: php bin/console doctrine:mapping:convert --from-database yml D:\db\ D:\test_b ...

  4. 在Winform窗体中使用WPF控件(附源码)

    原文:在Winform窗体中使用WPF控件(附源码) 今天是礼拜6,下雨,没有外出,闲暇就写一篇博文讲下如何在Winform中使用WPF控件.原有是我在百度上搜索相关信息无果,遂干脆动手自己实现. W ...

  5. Android 查看APK文件的签名算法

    查看APK使用了什么签名算法 keytool -list -printcert -jarfile xxx.apk 示例: 签名者 #1: 签名: 所有者: 发布者: 序列号: 有效期开始日期: 证书指 ...

  6. windows下捕获dump之Google breakpad_client

    breakpad是Google开源的一套跨平台工具,用于dump的处理.很全的一套东西,我这里只简单涉及breakpad客户端,不涉及纯文本符号生成,不涉及dump解析. 一.使用 最简单的是使用进程 ...

  7. Python Pandas 分析郁达夫《故都的秋》

    最近刚学这块,如果有错误的地方还请大家担待. 本文用到的Python包: Ipython, Numpy, Pandas, Matplotlib 故都的秋原文参考:http://www.xiexingc ...

  8. C#匹配中文字符串的4种正则表达式分享

    本文介绍在C#中使用匹配中文的正则表达式,包括纯中文.有中文.中文开头.中文结尾等几个正则表达式示例.在正则表达式中,中文可以通过Unicode编码来确定正则表达式范围. 在C#中,匹配中文的正则表达 ...

  9. 匹配中文字符的正则表达式: [/u4e00-/u9fa5]

    原文:匹配中文字符的正则表达式: [/u4e00-/u9fa5] 这里是几个主要非英文语系字符范围(google上找到的): 2E80-33FFh:中日韩符号区.收容康熙字典部首.中日韩辅助部首.注音 ...

  10. 什么是YAML?

    YAML是"YAML不是一种标记语言"的外语缩写 [1] (见前方参考资料原文内容):但为了强调这种语言以数据做为中心,而不是以置标语言为重点,而用返璞词重新命名.它是一种直观的能 ...