Description

题库链接

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

Solution

好久以前的坑了...

解法一

考虑树套树。

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

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

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

解法二

考虑 \(cdq\) 。

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

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

Code

解法一

//It is made by Awson on 2018.2.24
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int N = 100000;
void read(int &x) {
char ch; bool flag = 0;
for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
x *= 1-2*flag;
}
void print(LL x) {if (x > 9) print(x/10); putchar(x%10+48); }
void write(LL x) {if (x < 0) putchar('-'); print(Abs(x)); } int n, m, a, id[N+5]; LL ans;
struct Segment_tree {
int root[N+5], ch[N*100][2], key[N*100+5], pos;
int cpynode(int x) {++pos; ch[pos][0] = ch[x][0], ch[pos][1] = ch[x][1], key[pos] = key[x]; return pos; }
void insert(int &o, int l, int r, int loc, int val) {
if (o == 0) o = cpynode(o); key[o] += val;
if (l == r) return; int mid = (l+r)>>1;
if (loc <= mid) insert(ch[o][0], l, mid, loc, val); else insert(ch[o][1], mid+1, r, loc, val);
}
int query(int o, int l, int r, int a, int b) {
if ((a <= l && r <= b) || o == 0) return key[o];
int mid = (l+r)>>1;
int c1 = 0, c2 = 0;
if (a <= mid) c1 = query(ch[o][0], l, mid, a, b);
if (b > mid) c2 = query(ch[o][1], mid+1, r, a, b);
return c1+c2;
}
}ST;
struct bittree {
void add(int o, int val, int key) {for (; o <= n; o += lowbit(o)) ST.insert(ST.root[o], 1, n, val, key); }
int query(int o, int l, int r) {
int ans = 0;
for (; o; o -= lowbit(o)) ans += ST.query(ST.root[o], 1, n, l, r);
return ans;
}
}BT; void work() {
read(n); read(m);
for (int i = 1; i <= n; i++) read(a), BT.add(i, a, 1), ans += BT.query(i-1, a, n), id[a] = i;
for (int i = 1; i <= m; i++) {
writeln(ans); read(a);
ans -= BT.query(id[a]-1, a, n);
ans -= BT.query(n, 1, a);
ans += BT.query(id[a], 1, a);
BT.add(id[a], a, -1);
}
}
int main() {
work(); return 0;
}

解法二

//It is made by Awson on 2018.2.25
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int N = 1e5;
void read(int &x) {
char ch; bool flag = 0;
for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
x *= 1-2*flag;
}
void print(LL x) {if (x > 9) print(x/10); putchar(x%10+48); }
void write(LL x) {if (x < 0) putchar('-'); print(Abs(x)); } int n, m, match[N+5], d; LL ans[N+5];
struct tt {int x, y, t, flag; }a[N+5], b[N+5];
struct bittree {
int c[N+5];
void add(int o, int val) {for (; o <= n; o += lowbit(o)) c[o] += val; }
int query(int o) {int ans = 0; for (; o; o -= lowbit(o)) ans += c[o]; return ans; }
}T;
bool comp1(const tt &a, const tt &b) {return a.t < b.t; }
bool comp2(const tt &a, const tt &b) {return a.x < b.x; } void CDQ(int l, int r) {
if (l == r) return; int mid = (l+r)>>1;
for (int i = l; i <= mid; i++) b[i] = a[i], b[i].flag = 1;
for (int i = mid+1; i <= r; i++) b[i] = a[i], b[i].flag = 0;
sort(b+l, b+r+1, comp2);
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);
for (int i = l; i <= r; i++) if (b[i].flag == 1) T.add(b[i].y, -1);
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);
for (int i = l; i <= r; i++) if (b[i].flag == 1) T.add(b[i].y, -1);
CDQ(l, mid), CDQ(mid+1, r);
}
void work() {
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;
for (int i = 1; i <= m; i++) read(d), a[match[d]].t = times--;
for (int i = 1; i <= n; i++) if (a[i].t == 0) a[i].t = times--;
sort(a+1, a+n+1, comp1); CDQ(1, n);
LL Ans = 0; for (int i = 1; i <= n; i++) Ans += ans[i];
for (int i = n; i > n-m; i--) writeln(Ans), Ans -= ans[i];
}
int main() {
work(); return 0;
}

[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. Beta版本敏捷冲刺每日报告——Day2

    1.情况简述 Beta阶段第二次Scrum Meeting 敏捷开发起止时间 2017.11.3 08:00 -- 2017.11.3 22:00 讨论时间地点 2017.11.3晚9:00,软工所实 ...

  2. 高校学生征信系统Postmortem结果

    Postmortem结果 设想和目标 1 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件需要解决的问题是当前高校学生征信系统建设薄弱的问题,我们试图建立 ...

  3. 基于scrapy爬虫的天气数据采集(python)

    基于scrapy爬虫的天气数据采集(python) 一.实验介绍 1.1. 知识点 本节实验中将学习和实践以下知识点: Python基本语法 Scrapy框架 爬虫的概念 二.实验效果 三.项目实战 ...

  4. IQKeyboardManager使用方法

    使用方法: 将IQKeyboardManager 和 IQSegmentedNextPrevious类文件加进项目中.在AppDelegate文件中写下以下一行代码: [IQKeyBoardManag ...

  5. 11-移动端开发教程-zepto.js入门教程

    Zepto.js是一个轻量级的针对现代浏览器的JavaScript库, 它与jquery有着类似的api. 如果你会用jquery,那么你也会用zepto. 1. Why Zepto.js? API类 ...

  6. 07-TypeScript的For循环

    在传统的JavaScript中,关于循环,可以有两种方式,一种是forEach,一种是for. forEach的用法如下: var sarr=[1,2,3,4]; sarr.desc="he ...

  7. Python内置函数(18)——bin

    英文文档: bin(x) Convert an integer number to a binary string. The result is a valid Python expression. ...

  8. layui中进行form表单一些问题

    最近一段时间一直在用layui来写一些前段页面,发现有几个问题,不知道是我的编译器的问题还是什么,总之目前是自己改成功了,在这里分享下. 第一个是用layui去写单选按钮,网页上不会显示出来.解决方法 ...

  9. mosquitto安装和测试

    一.安装 1.windows安装 安装完毕,更新安装目录的dll文件 2.linux安装 编译保存用户数据到数据库的插件 安装 3.启动 mosquitto mosquitto mosquitto_p ...

  10. HTTP协议扫盲(七)请求报文之 GET、POST-FORM 和 POST-FILE

    一.get 1.页面代码 2.请求报文 3.小结 get请求没有报文体,所以请求报文没有content-type url上的query参数param11=val11&param12=val12 ...