求逆序对 (树状数组版)

基本思想和线段树求解逆序数是一样的,前一篇《求逆序对 线段树版》也介绍过,先对输入数组离散,数组里的元素都不相同可以直接hash,存在相同的数话可以采用二分。

离散化后对于每个f[i],找到f[i]+1~ n中的个数,也就是到i这个位置,一共有多少比f[i]大的数,统计之后在将f[i]的位置上的数量加1。

这样一来统计的就是类似a[i]~n的和,可以想象成 把树状数组反过来统计,即统计的时候加lowbit,更新的时候减lowbit。

还是 以POJ 2299为例。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <stack>
#include <cctype>
#include <algorithm>
#define lson o<<1, l, m
#define rson o<<1|1, m+1, r
using namespace std;
typedef long long LL;
const int maxn = 500050;
const int mod = 99999997;
const int MAX = 0x3f3f3f3f;
int n, tmp, f[maxn];
LL c[maxn];
struct C {
    int num, pos;
}in[maxn];
bool cmp(C x, C y) {
    return x.num < y.num;
}
int main()
{
    while(cin >> n, n) {
        for(int i = 1; i <= n; i++) {
            scanf("%d", &in[i].num);
            in[i].pos = i;
        }
        sort(in+1, in+1+n, cmp);
        LL sum = 0;
        memset(c, 0, sizeof(c));
        for(int i = 1; i <= n; i++) f[ in[i].pos ] = i;
        for(int i = 1; i <= n; i++) {
            for(int j = f[i]+1; j <= n; j += j&(-j))
                sum += c[j];
            for(int j = f[i]; j > 0; j -= j&(-j))
                c[j]++;
        }
        cout << sum << endl;
    }
    return 0;
}

求逆序对 (树状数组版)

时间: 2024-12-17 03:08:32

求逆序对 (树状数组版)的相关文章

求逆序对[树状数组] jdoj

求逆序对 题目大意:给你一个序列,求逆序对个数. 注释:n<=$10^5$. 此题显然可以跑暴力.想枚举1到n,再求在i的后缀中有多少比i小的,统计答案即可.这显然是$n^2$的.这...显然过不去,我们思考如何优化?显然,这里的有些过程是重复的.我们将这个序列设为a序列,对于两个1到n中的整数i<j,在j后面的数我们进行了多次重复枚举,我们思考如何优化.容易想到用一个桶来记录.只需要记录对于每一个数来讲,我后面有多少个数是比我小的,只需要将桶中的数累加即可.但是,我们必须记录是这个数之后的桶

BZOJ3295 CQOI2011 动态逆序对 树状数组套线段树

离线倒着做,每次加入一个节点后新增的逆序对数量就是其左边大于它的数的个数(左边数的总数-左边小于它的数的个数)+右边小于它的数的个数 用树状数组维护求和,对于树状数组中每个节点v所对应的区间线段树维护区间[l,r]中大于v的数的个数. 最后唯一的问题就是指针版线段树MLE-- #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <alg

【2018.12.15】【考试总结】【模拟+逆序对+树状数组+贪心+multiset】爆零之旅

这是我悲惨的接近爆零的一次考试,但是本蒟蒻不能放弃,还是要总结的QAQ 答题卡 [题目背景] 八月是个悲惨的月份.先不谈炎热的天气,对于新生来说,八月意味着军训: 而对于高二高三的同学来说,八月意味着开学考试.而考试就意味着改卷,改卷 也就意味着答题卡.不幸的是,学校读答题卡的机器的评分软件坏了,wyx 就被 老师要求写一个评分的程序. [问题描述] 软件需要读入学生的姓名.试题答案以及学生的答题卡信息. 学生姓名 学校的信息管理系统中存储了所有学生的姓名,一共 名学生.每个学生的 名字的组成只

POJ - 2299 - Ultra-QuickSort = 归并排序 + 逆序对 / 树状数组

http://poj.org/problem?id=2299 求逆序对最简单的绝对不会是树状数组,一定是归并排序(认真),不过树状数组会不会快一点呢?理论上应该是树状数组快一点(假如不进行离散化). #include<algorithm> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<map> #include<set

BZOJ 3295 [Cqoi2011]动态逆序对 树状数组套线段树

题意:链接 方法:树状数组套线段树 解析: 这题基本上写的都是什么CDQ点分治,主席树之类的,然而这我都并不会,所以写了一发平衡树套线段树想卡时卡过去,然而我并没有得逞,T的不要不要的,这里用平衡树套线段树的方法参见我的题解:排队.这道题比那道更要简单. 然后我就打算弃坑了~不过看140142做这道题做的热火朝天的,还是打算回来做一下,yy下树状数组套线段树,然后去看hz的题解,只看懂他写理论部分了,代码部分不知所云,所以还是还是得yy.引用理论部分. 删除某个数,只要统计它之前还存在的比它大的

luogu P1908 逆序对 |树状数组

题目描述 猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计.最近,TOM老猫查阅到一个人类称之为"逆序对"的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对.知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目. Update:数据已加强. 输入格式 第一行,一个数n,表示序列中有n个数. 第二行n个数,表示给定的序列.序列中每个数字不超过10

POJ_3067 Japan[ 逆序数 树状数组 or 归并排序)

传送门:POJ_3067 题目:n,m,k;左右两列数,数的范围分别1-n,1-m,然给k个连线. Sample Input 1 3 4 4 1 4 2 3 3 2 3 1 Sample Output Test case 1: 5 思路:逆序数 代码: //树状数组版 //块状数组 #include<iostream> #include<cstring> #include<cmath> #include<cstdio> #include<algorit

CF #261 div2 D. Pashmak and Parmida&amp;#39;s problem (树状数组版)

Parmida is a clever girl and she wants to participate in Olympiads this year. Of course she wants her partner to be clever too (although he's not)! Parmida has prepared the following test problem for Pashmak. There is a sequence a that consists of n

HPU1291 小朋友排队 【逆序数+树状数组】

1291: 小朋友排队 时间限制: 1 Sec  内存限制: 128 MB 提交: 2  解决: 1 [提交][状态][讨论版] [Edit] 题目描述 n 个小朋友站成一排.现在要把他们按身高从低到高的顺序排列,但是每次只能交换位置相邻的两个小朋友. 每个小朋友都有一个不高兴的程度.开始的时候,所有小朋友的不高兴程度都是0. 如果某个小朋友第一次被要求交换,则他的不高兴程度增加1,如果第二次要求他交换,则他的不高兴程度增加2(即不高兴程度为3),依次类推.当要求某个小朋友第k次交换时,他的不高