Description

题库链接

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

Solution

好久以前的坑了...

解法一

考虑树套树。

删去一个数,减少的逆序对个数是当前位置之前比当前数大的个数以及在这个数的位置之后比当前数小的个数。

如果不支持修改显然是可以用主席树来维护的。

由于要支持修改,我们考虑用树状数组套线段树,树状数组维护序列下标。线段树维护数的个数。那么时间和空间复杂度都是 \(O(n\cdot log^2_2 n)\) 的。

解法二

考虑 \(cdq\) 。

首先删数很不好操作,我们考虑从后往前操作,让删数变成添数。

我们可以先按时间排序。添加时间早的数才会对添加时间晚的有贡献。对于 \(cdq\) 的每一次操作就是统计添数时间早于某个数的当前位置之前比当前数大的个数以及在这个数的位置之后比当前数小的个数。

Code

解法一

  1. //It is made by Awson on 2018.2.24
  2. #include <bits/stdc++.h>
  3. #define LL long long
  4. #define dob complex<double>
  5. #define Abs(a) ((a) < 0 ? (-(a)) : (a))
  6. #define Max(a, b) ((a) > (b) ? (a) : (b))
  7. #define Min(a, b) ((a) < (b) ? (a) : (b))
  8. #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
  9. #define writeln(x) (write(x), putchar('\n'))
  10. #define lowbit(x) ((x)&(-(x)))
  11. using namespace std;
  12. const int N = 100000;
  13. void read(int &x) {
  14. char ch; bool flag = 0;
  15. for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
  16. for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
  17. x *= 1-2*flag;
  18. }
  19. void print(LL x) {if (x > 9) print(x/10); putchar(x%10+48); }
  20. void write(LL x) {if (x < 0) putchar('-'); print(Abs(x)); }
  21. int n, m, a, id[N+5]; LL ans;
  22. struct Segment_tree {
  23. int root[N+5], ch[N*100][2], key[N*100+5], pos;
  24. int cpynode(int x) {++pos; ch[pos][0] = ch[x][0], ch[pos][1] = ch[x][1], key[pos] = key[x]; return pos; }
  25. void insert(int &o, int l, int r, int loc, int val) {
  26. if (o == 0) o = cpynode(o); key[o] += val;
  27. if (l == r) return; int mid = (l+r)>>1;
  28. if (loc <= mid) insert(ch[o][0], l, mid, loc, val); else insert(ch[o][1], mid+1, r, loc, val);
  29. }
  30. int query(int o, int l, int r, int a, int b) {
  31. if ((a <= l && r <= b) || o == 0) return key[o];
  32. int mid = (l+r)>>1;
  33. int c1 = 0, c2 = 0;
  34. if (a <= mid) c1 = query(ch[o][0], l, mid, a, b);
  35. if (b > mid) c2 = query(ch[o][1], mid+1, r, a, b);
  36. return c1+c2;
  37. }
  38. }ST;
  39. struct bittree {
  40. void add(int o, int val, int key) {for (; o <= n; o += lowbit(o)) ST.insert(ST.root[o], 1, n, val, key); }
  41. int query(int o, int l, int r) {
  42. int ans = 0;
  43. for (; o; o -= lowbit(o)) ans += ST.query(ST.root[o], 1, n, l, r);
  44. return ans;
  45. }
  46. }BT;
  47. void work() {
  48. read(n); read(m);
  49. for (int i = 1; i <= n; i++) read(a), BT.add(i, a, 1), ans += BT.query(i-1, a, n), id[a] = i;
  50. for (int i = 1; i <= m; i++) {
  51. writeln(ans); read(a);
  52. ans -= BT.query(id[a]-1, a, n);
  53. ans -= BT.query(n, 1, a);
  54. ans += BT.query(id[a], 1, a);
  55. BT.add(id[a], a, -1);
  56. }
  57. }
  58. int main() {
  59. work(); return 0;
  60. }

解法二

  1. //It is made by Awson on 2018.2.25
  2. #include <bits/stdc++.h>
  3. #define LL long long
  4. #define dob complex<double>
  5. #define Abs(a) ((a) < 0 ? (-(a)) : (a))
  6. #define Max(a, b) ((a) > (b) ? (a) : (b))
  7. #define Min(a, b) ((a) < (b) ? (a) : (b))
  8. #define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
  9. #define writeln(x) (write(x), putchar('\n'))
  10. #define lowbit(x) ((x)&(-(x)))
  11. using namespace std;
  12. const int N = 1e5;
  13. void read(int &x) {
  14. char ch; bool flag = 0;
  15. for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
  16. for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
  17. x *= 1-2*flag;
  18. }
  19. void print(LL x) {if (x > 9) print(x/10); putchar(x%10+48); }
  20. void write(LL x) {if (x < 0) putchar('-'); print(Abs(x)); }
  21. int n, m, match[N+5], d; LL ans[N+5];
  22. struct tt {int x, y, t, flag; }a[N+5], b[N+5];
  23. struct bittree {
  24. int c[N+5];
  25. void add(int o, int val) {for (; o <= n; o += lowbit(o)) c[o] += val; }
  26. int query(int o) {int ans = 0; for (; o; o -= lowbit(o)) ans += c[o]; return ans; }
  27. }T;
  28. bool comp1(const tt &a, const tt &b) {return a.t < b.t; }
  29. bool comp2(const tt &a, const tt &b) {return a.x < b.x; }
  30. void CDQ(int l, int r) {
  31. if (l == r) return; int mid = (l+r)>>1;
  32. for (int i = l; i <= mid; i++) b[i] = a[i], b[i].flag = 1;
  33. for (int i = mid+1; i <= r; i++) b[i] = a[i], b[i].flag = 0;
  34. sort(b+l, b+r+1, comp2);
  35. for (int i = l; i <= r; i++) if (b[i].flag == 1) T.add(b[i].y, 1); else ans[b[i].t] += T.query(n)-T.query(b[i].y);
  36. for (int i = l; i <= r; i++) if (b[i].flag == 1) T.add(b[i].y, -1);
  37. for (int i = r; i >= l; i--) if (b[i].flag == 1) T.add(b[i].y, 1); else ans[b[i].t] += T.query(b[i].y);
  38. for (int i = l; i <= r; i++) if (b[i].flag == 1) T.add(b[i].y, -1);
  39. CDQ(l, mid), CDQ(mid+1, r);
  40. }
  41. void work() {
  42. read(n), read(m); for (int i = 1; i <= n; i++) read(a[i].y), a[i].x = i, match[a[i].y] = i; int times = n;
  43. for (int i = 1; i <= m; i++) read(d), a[match[d]].t = times--;
  44. for (int i = 1; i <= n; i++) if (a[i].t == 0) a[i].t = times--;
  45. sort(a+1, a+n+1, comp1); CDQ(1, n);
  46. LL Ans = 0; for (int i = 1; i <= n; i++) Ans += ans[i];
  47. for (int i = n; i > n-m; i--) writeln(Ans), Ans -= ans[i];
  48. }
  49. int main() {
  50. work(); return 0;
  51. }

[CQOI 2011]动态逆序对的更多相关文章

  1. cdq分治(hdu 5618 Jam's problem again[陌上花开]、CQOI 2011 动态逆序对、hdu 4742 Pinball Game、hdu 4456 Crowd、[HEOI2016/TJOI2016]序列、[NOI2007]货币兑换 )

    hdu 5618 Jam's problem again #include <bits/stdc++.h> #define MAXN 100010 using namespace std; ...

  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. 【Luogu1393】动态逆序对(CDQ分治)

    [Luogu1393]动态逆序对(CDQ分治) 题面 题目描述 对于给定的一段正整数序列,我们定义它的逆序对的个数为序列中ai>aj且i < j的有序对(i,j)的个数.你需要计算出一个序 ...

  5. 【BZOJ3295】动态逆序对(线段树,树状数组)

    [BZOJ3295]动态逆序对(线段树,树状数组) 题面 Description 对于序列A,它的逆序对数定义为满足iAj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的 ...

  6. bzoj3295[Cqoi2011]动态逆序对 树套树

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

  7. P3157 [CQOI2011]动态逆序对(树状数组套线段树)

    P3157 [CQOI2011]动态逆序对 树状数组套线段树 静态逆序对咋做?树状数组(别管归并QWQ) 然鹅动态的咋做? 我们考虑每次删除一个元素. 减去的就是与这个元素有关的逆序对数,介个可以预处 ...

  8. P3157 [CQOI2011]动态逆序对

    P3157 [CQOI2011]动态逆序对 https://www.luogu.org/problemnew/show/P3157 题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai&g ...

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

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

随机推荐

  1. MySQL的学习记录(3.31更新)

    MySQL的学习记录(3.31更新) 0x00 安装及配置 Windows 1.首先官网下载(https://dev.mysql.com/downloads/mysql/) ps:不想官网下载的可以到 ...

  2. MongoDB系列三(Spring集成方案).

    一.前言 MongoDB是最为流行的开源文档数据库之一.Spring Data MongoDB提供了三种方式在Spring应用中使用MongoDB: 通过注解实现对象-文档映射: 使用MongoTem ...

  3. .NET Core初体验 在window上构建第一个app

    ASP.NET Core 是一个跨平台,高性能的开源框架,用于构建现代化的,基于云的互联网应用程序.使用 ASP.NET Core ,您可以: 构建Web应用程序和服务,IoT应用程序和移动后端. 在 ...

  4. Java虚拟机16:Metaspace

    被废弃的持久代 想起之前面试的时候有面试官问起过我一个问题:Java 8为什么要废弃持久代即Metaspace的作用.由于当时使用的Java 7且研究重心不在JVM上,一下没有回答上来,今天突然想起这 ...

  5. Welcome to StackEdit!

    Welcome to StackEdit! Hey!our first Markdown document in StackEdit1. Don't delete me, I'm very helpf ...

  6. 【Alpha版本】冲刺阶段 - Day1 - 启航

    Alpha 阶段成员分工及任务量 成员 分工 任务量(小时) 袁逸灏 完成app用户车辆,子弹发射,背景移动,暂停界面,音乐界面,音乐查找,音乐播放 25 刘伟康 项目进度把控.分配任务.组织会议.整 ...

  7. 2017 国庆湖南 Day5

    期望得分:76+80+30=186 实际得分:72+10+0=82 先看第一问: 本题不是求方案数,所以我们不关心 选的数是什么以及的选的顺序 只关心选了某个数后,对当前gcd的影响 预处理 cnt[ ...

  8. python time、datetime、random、os、sys模块

    一.模块1.定义模块:用来从逻辑上组织Python代码(变量,函数,类,逻辑:实现一个功能),本质就是.py结尾的python文件(文件名:test.py,对应的模块名:test)包:用来从逻辑上组织 ...

  9. 使用URL访问http服务器

    一.概念定义 1.URI - 通用资源标识符 URI通常由三部分组成, 资源访问机制 存放资源的主机名 资源自身名称 如: http://www.baidu.com/html http://www.b ...

  10. 使用 slf4j抽象日志层 和 其他日志实现对接

    前言 如果你正在提供一个开源的Java-jar,那么让你的项目仅依赖slf4j-api然后让你的用户在他们开发和运营环境中选择任意的日志实现绝对是个好想法,.作为终端用户,他们可以快速地从上面提到的日 ...