`

树状数组求逆序数(离散化)

阅读更多

树状数组是一种能快速求出前n项和的数据结构,

例如:数组a0,a1,a2,a3,a4,a5....an。

sum(a[4])求的就是a0+a1+a2+a3+a4。

sum(a[n]-a[4])求的就是a5+...+an。

时间复杂度为o(nlogn)。

 

离散化  就是把原来的一组数变成另一组数,但是他们的相对大小不变。比如

把       4  6  8  9  2

变成   2  3  4  5  1

他们的逆序数不变

 

下面贴代码:

#include<iostream>
#include<cmath>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAXN=1000000+5;
int b[MAXN],c[MAXN];
int n;
struct node
{
	int num,id;
}a[MAXN];
bool cmp(node a,node b)
{
	return(a.num<b.num);
}
void add(int i)//更新树状数组
{
	while(i<=n)
	{
		c[i]++;
		i+=i&(-i);
	}
}
int sum(int i)//树状数组求和
{
	int totle;
	while(i>0)
	{
		totle+=c[i];
		i-=i&(-i);
	}
	return(totle);
}
int main()
{
	int i,T;
	__int64 ans;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		memset(b,0,sizeof(b));
		memset(c,0,sizeof(c));
		for(i=1;i<=n;i++)
		{
			scanf("%d",&a[i].num);//记录数据
			a[i].id=i;//记录是第几个输入的
		}
		sort(a+1,a+n+1,cmp);
		b[a[1].id]=1;//最小的那个变成1,次小的那个变成2,以此类推...
		for(i=2;i<=n;i++)
		{
			if(a[i].num!=a[i-1].num)
				b[a[i].id]=i;
			else b[a[i].id]=b[a[i-1].id];
		}
		ans=0;
		for(i=1;i<=n;i++)
		{
			add(b[i]);
			ans+=(__int64)(sum(n)-sum(b[i]));//求到目前为止比这个数大的有多少个
		}
		printf("%I64d\n",ans);
	}
	return(0);
}

 

4
0
分享到:
评论

相关推荐

    树状数组(Binary Indexed Tree,BIT)高效地处理动态的区间求和问题

    3. **离散化:** 将一个区间的值映射到一个连续的区间上,从而使得区间和的计算更为方便。这种技术在处理具有大量重复数值的问题时尤为有效。 4. **动态规划:** 在某些动态规划问题中,树状数组可以用来优化状态...

    ACM算法模板和pku代码

    归并排序求逆序数 Pell方程 Catalan数,100以内 欧拉函数讲解 组合计数 组合数计算(double) 组合数计算(高精度) r-组合生成算法 r-排列生成算法 r-错位排列生成算法 图论 传递闭包 欧拉回路判定 有向图...

    广工《算法和高级数据结构教程》

    在解决逆序对问题时,首先需要对数列进行离散化处理,使得数据更加紧凑。通过树状数组的特性,每次插入一个数值时,可以统计比当前数值小的数的个数,进而快速计算出逆序对的总数。树状数组的关键操作包括update和...

    ACM巨全模板 .pdf

    9,树状数组模板 (求区间异或和,求逆序对) 扩展 10.区间不重复数字的和 (树状数组) 11.求k维空间中离所给点最近的m个点,并按顺序输出(KD树) 12.LCA (两个节点的公共父节点) 动态规划: 1.LIS (最长上升子序列) 2.有...

    线段树汇总

    线段树是一种树形数据结构,每个节点代表一个区间,通常用于处理区间上的最大值、最小值、累加和等统计问题。线段树将区间分为左右两个子区间,这样可以通过递归的方式实现区间查询和更新。 2. **线段树的构造**:...

    浙江大学ACM模板 计算几何,图论,数据结构,经典题的模板

    7.7 离散化 157 8.图论 158 8.0 2-SAT 158 8.2 寻找Euler回路 163 8.3 拓扑排序 163 8.4 差分约束系统 164 8.5 笛卡尔树 165 8.6 LCA和RMQ 167 8.7 割和桥 171 8.8 最小生成树(kruskal) 172 8.9 最短路径 173 8.10 ...

    PKU 图论 DP 解题报告

    - **算法讨论**:考虑到数据范围较大,首先需要对输入的数值进行离散化处理,将其映射到较小的整数集合中。接着,使用四个树状数组分别记录每个数作为组合中特定位置(例如第一位、第二位等)时的情况数。对于每个数...

    线段树题目

    - **POJ 1151**:结合了线段树和离散化的技巧来求解矩形面积的并集。这需要对输入的坐标进行离散化处理,以减少空间复杂度,并使用线段树维护区间信息。 - **POJ 1177**:求解矩形周长的并集。此题与POJ 1151类似,...

    福州大学ACM模板

    - **归并排序求逆序数**:归并排序的过程中统计逆序数的方法。 - **日期计算**:涉及到日期和时间的处理,如计算两个日期之间的天数等。 - **KMP算法**:字符串匹配的经典算法。 - **字符串最小表示法**:将字符串...

    c常用算法程序集 c算法

    5. 树形结构: - 遍历:前序、中序和后序遍历,以及层次遍历,理解树的结构和操作。 - 查找二叉树:二分查找树、AVL树、红黑树等,保持平衡以提高查找效率。 6. 字符串处理: - KMP算法:避免回溯,提高了模式...

    基本算法模块.doc

    - **扩展欧几里得算法**:不仅求出最大公约数,还能求出两个整数的互逆元,常用于模运算。 - **线性同余方程求解**:在数论中,解决形如ax ≡ b (mod m)的方程。 3. **排列组合**: - **排列生成**:算法用于...

Global site tag (gtag.js) - Google Analytics