COGS-1715 [CQOI2011]动态逆序对(树状数组+线段树)
来源:互联网 发布:口袋助理软件 编辑:程序博客网 时间:2024/05/16 10:04
1715. [CQOI2011]动态逆序对
★★★ 输入文件:inverse.in
输出文件:inverse.out
简单对比时间限制:2 s 内存限制:128 MB
【题目描述】
对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。
【输入格式】
输入第一行包含两个整数n和m,即初始元素的个数和删除的元素个数。以下n行每行包含一个1到n之间的正整数,即初始排列。以下m行每行一个正整数,依次为每次删除的元素。
【输出格式】
输出包含m行,依次为删除每个元素之前,逆序对的个数。
【样例输入】
5 4 1 5 3 4 2 5 1 4 2
【样例输出】
5 2 2 1 样例解释 (1,5,3,4,2)(1,3,4,2)(3,4,2)(3,2)(3)。
【提示】
N<=100000 M<=50000
首先用树状数组求一下原始的逆序对,每次删除一个数x的时候,ans-=x后面比x小的数+x前面比x大的数
当然这样算会有重复,因为有些数有可能已经删去了,因此可以用一个二维变量(i,a[i])记录已经删去的值,用树状数组+线段树维护一下即可。时间复杂度O(nlog^2n)
(其实可以用CDQ分治来写,,,不过还是树写起来爽
#include<bits/stdc++.h>using namespace std;typedef long long LL;const int MX = 1e5 + 5;const int MXM = MX * 80;int n, m, cnt;int sum[MXM], ls[MXM], rs[MXM];int a[MX], fa[MX];LL f[MX];struct Tree { int n; vector <LL> T; void init(int _n) { T.clear(); n = _n; T.resize(n + 1); } void add(int x, LL v) { for (int i = x; i <= n; i += i & -i) T[i] += v; } LL sum(int x) { if (x > n) x = n; LL ret = 0; for (int i = x; i > 0; i -= i & -i) ret += T[i]; return ret; }} T;void update(int p, int val, int l, int r, int prt, int &rt) { rt = ++cnt; ls[rt] = ls[prt]; rs[rt] = rs[prt]; sum[rt] = sum[prt] + 1; if (l == r) return; int m = (l + r) >> 1; if (p <= m) update(p, val, l, m, ls[prt], ls[rt]); else update(p, val, m + 1, r, rs[prt], rs[rt]);}int query(int L, int R, int l, int r, int rt) { if (L <= l && R >= r) return sum[rt]; int m = (l + r) >> 1, ret = 0; if (L <= m) ret += query(L, R, l, m, ls[rt]); if (R > m) ret += query(L, R, m + 1, r, rs[rt]); return ret;}struct BTree { int n; vector <int> T; void init(int _n) { T.clear(); n = _n; T.resize(n + 1); } void add(int x, int y, int v) { for (int i = x; i <= n; i += i & -i) update(y, v, 1, n, T[i], T[i]); } int sum(int x, int l, int r) { if (x > n) x = n; int ret = 0; for (int i = x; i > 0; i -= i & -i) ret += query(l, r, 1, n, T[i]); return ret; }} bt;int main() { //freopen("in.txt", "r", stdin); freopen("inverse.in", "r", stdin); freopen("inverse.out", "w+", stdout); scanf("%d%d", &n, &m); T.init(n); bt.init(n); for (int i = 1; i <= n; i++) scanf("%d", &a[i]), fa[a[i]] = i; LL ans = 0; for (int i = n; i > 0; i--) { f[i] = T.sum(a[i]); ans += f[i]; T.add(a[i], 1); } for (int i = 1, x; i <= m; i++) { printf("%lld\n", ans); scanf("%d", &x); int index = fa[x]; ans -= 2 * f[index] + index - x; ans += bt.sum(index, x, n); ans += bt.sum(n, 1, x) - bt.sum(index, 1, x); bt.add(index, x, 1); } return 0;}
阅读全文
0 0
- COGS-1715 [CQOI2011]动态逆序对(树状数组+线段树)
- bzoj3295: [Cqoi2011]动态逆序对 树状数组套线段树
- 【BZOJ】3295 [Cqoi2011]动态逆序对 树状数组+线段树
- [BZOJ3295][Cqoi2011]动态逆序对(树状数组套线段树||cdq分治)
- 【树状数组+线段树动态开点】BZOJ3295(Cqoi2011)[动态逆序对]题解
- BZOJ 3295 [Cqoi2011]动态逆序对 树状数组套线段树
- 【bzoj3295】 CQOI2011动态逆序对 树状数组+主席树
- 3295: [Cqoi2011]动态逆序对 树状数组套主席树
- BSOJ2841:CQOI2011动态逆序对 树状数组套平衡树
- 【bzoj3295】[Cqoi2011]动态逆序对 树状数组套主席树
- 【bzoj3295】【Cqoi2011】【动态逆序对】【树状数组套平衡树】
- BZOJ 3295: [Cqoi2011]动态逆序对 (树状数组套主席树)
- bzoj 3295: [Cqoi2011]动态逆序对 cdq分治+树状数组
- [BZOJ3295][CQOI2011]动态逆序对-CDQ分治+树状数组
- bzoj 3295: [Cqoi2011]动态逆序对 (CDQ分治+树状数组)
- bzoj3295 动态逆序对【树状数组套权值线段树】
- bzoj3295[Cqoi2011]动态逆序对(cdq分治||可持久化线段树)
- CQOI2011-动态逆序对
- POJ
- 如何区分Oracle的数据库,实例,服务名,SID
- maven小笔记
- 项目之间Cookie的共享
- Mysql数据库常用引擎
- COGS-1715 [CQOI2011]动态逆序对(树状数组+线段树)
- Maven创建web项目
- Jsoup获取网页全部原始内容
- Android多进程压缩图片库
- HDU
- Wavel Sequence HDU
- pitch yaw roll是什么
- 硬件电路的设计流程(两层板)
- MySQL行级锁、表级锁、页级锁