[CQOI 2011]动态逆序对
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]动态逆序对的更多相关文章
- 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; ...
- BZOJ 3295: [Cqoi2011]动态逆序对
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3865 Solved: 1298[Submit][Sta ...
- Bzoj 3295: [Cqoi2011]动态逆序对 分块,树状数组,逆序对
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2886 Solved: 924[Submit][Stat ...
- 【Luogu1393】动态逆序对(CDQ分治)
[Luogu1393]动态逆序对(CDQ分治) 题面 题目描述 对于给定的一段正整数序列,我们定义它的逆序对的个数为序列中ai>aj且i < j的有序对(i,j)的个数.你需要计算出一个序 ...
- 【BZOJ3295】动态逆序对(线段树,树状数组)
[BZOJ3295]动态逆序对(线段树,树状数组) 题面 Description 对于序列A,它的逆序对数定义为满足iAj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的 ...
- bzoj3295[Cqoi2011]动态逆序对 树套树
3295: [Cqoi2011]动态逆序对 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 5987 Solved: 2080[Submit][Sta ...
- P3157 [CQOI2011]动态逆序对(树状数组套线段树)
P3157 [CQOI2011]动态逆序对 树状数组套线段树 静态逆序对咋做?树状数组(别管归并QWQ) 然鹅动态的咋做? 我们考虑每次删除一个元素. 减去的就是与这个元素有关的逆序对数,介个可以预处 ...
- P3157 [CQOI2011]动态逆序对
P3157 [CQOI2011]动态逆序对 https://www.luogu.org/problemnew/show/P3157 题目描述 对于序列A,它的逆序对数定义为满足i<j,且Ai&g ...
- 2018.07.01 BZOJ3295: [Cqoi2011]动态逆序对(带修主席树)
3295: [Cqoi2011]动态逆序对 **Time Limit: 10 Sec Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j& ...
随机推荐
- Java读取文件存储到mysql
写了一批Lua脚本,要放到数据库里面,调用的时候进行计算,由于有太多lua脚本,就写了个程序来录入. 下面主要分三个部分: public static String readToString(Stri ...
- 201621123040《Java程序设计》第13周学习总结
1.本周学习总结 2.为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 2.1简述你想为你的系统增加什么网络功能?设计思路是什么? 创建服务器端端口(3333),当用户以客户端身份访问 ...
- Dijkstra算法课后补分博客
题目名称:Dijkstra算法 题目要求:课上给出相关附图,求解附图顶点A的单源最短路径. 附图: 做题过程 1.了解Dijkstra算法的相关知识,包括定义以及使用方法. 定义:Dijkstra算法 ...
- 第三篇:Python字符编码
一 .了解字符编码的知识储备 1计算机基础知识 1.2文本编辑器存取文件的原理(nodepat++,Pycharm,word) #.打开编辑器就打开了启动了一个进程,是在内存中的,所以,用编辑器编写的 ...
- JAVA_SE基础——29.构造函数
黑马程序员入学Blog... jvm创建Java对象时候需要调用构造器,默认是不带参数的.在构造器中,你可以让jvm帮你初始化一些参数或者执行一系列的动作. 它是对象创建中执行的函数,及第一个被执行的 ...
- ORA-00379 缓冲池 DEFAULT 中无法提供 32K 块大小的空闲缓冲区
(一)问题 今天在使用Pl/sql developer查看表空间大小的时候,报错误:ORA-00379 缓冲池 DEFAULT 中无法提供 32K 块大小的空闲缓冲区,具体如下图: SQL> s ...
- redis 持久化之 RDB
redis的运维过程中,我们对数据持久化做一个基本的总结. 1什么是持久化: redis 所有数据保持在内存中,对数据的更新将异步地保存到磁盘上. RDB 文件创建的过程是直接从内存 写入到我们我磁盘 ...
- Python-函数-Day4
1.函数 1.1.集合 主要作用: 去重 关系测试, 交集\差集\并集\反向(对称)差集 a = {1,2,3,4} b ={3,4,5,6} a {1, 2, 3, 4} type(a) <c ...
- 请求方式:request和 get、post、put
angular 的 http 多了 Request, Headers, Response ,这些都是游览器的"新特性" Fetch API. Fetch API 和以前的 xmlh ...
- Tomcat8.0 配置环境
(1)首先安装JDk 下载jdk进行安装后进行配置环境 新增一个Java_Home的变量复制本地安装目录的路径:eg:C:\Program Files (x86)\Java\jdk1.8.0_141\ ...