hdu1394 树状数组 解法

本题使用树状数组果然更加快。

树状数组难点:

1 如何遍历树

2 如何利用数组数据

建立一个树状数组就如上图红色部分代表所有的树状数组节点了。

基本操作:

查找下一个节点的计算,如不明白下面函数的作用,请查看负数内存存放的问题。

简而言之就是:内存放是求反+1; 利用这个函数可以神奇地寻找到其单亲节点和兄弟节点,比如上图6->8,6->4或者7->8, 7 -> 6这样跳转节点。

这是树状数组实现的关键了,理解了如何遍历这样的树,就会使用这个数据结构了。

inline int lowbit(int x)
	{
		return x & (-x);//or return x&(x^(x-1));
	}

更新节点:

void update(int i, int val, int len)
	{
		while (i <= len)
		{
			c[i] += val;
			i += lowbit(i);
		}
	}

求和操作:

int getsum(int x)
	{
		int ans = 0;
		while (x > 0)
		{
			ans += c[x];
			x -= lowbit(x);
		}
		return ans;
	}

参考资料:

http://www.cppblog.com/Ylemzy/articles/98322.html

主要是看图,然后自己思考,看代码吧。

解决这道题的代码:

class MinimumInversionNumber_3_TreeArray
{
	static const int SIZE = 5005;
	int *a, *c;//一般数组和树状数组
	inline int lowbit(int x)
	{
		return x & (-x);//or return x&(x^(x-1));
	}

	void update(int i, int val, int len)
	{
		while (i <= len)
		{
			c[i] += val;
			i += lowbit(i);
		}
	}

	int getsum(int x)
	{
		int ans = 0;
		while (x > 0)
		{
			ans += c[x];
			x -= lowbit(x);
		}
		return ans;
	}
public:
	MinimumInversionNumber_3_TreeArray() : a((int*)malloc(sizeof(int)*SIZE)),
		c((int*)malloc(sizeof(int)*SIZE))
	{
		int n, t;
		while(~scanf("%d",&n))
		{
			for(int i = 1; i <= n; i++)
			{
				scanf("%d", &t);
				a[i] = t + 1;
			}  

			//memset(c, 0, sizeof(c));最好不要使用memset设置初值
			fill(c, c+n+1, 0);
			int res = 0;
			for(int i = 1; i <= n; i++)
			{
				update(a[i], 1, n);
				res += i - getsum(a[i]);//目前为止,出现了多少个小于等于a[i]的数位getsum(a[i]),所以大于a[i]的数位i-getsum(a[i]),即为逆序数
			}
			int ans = res;
			for(int i = 2; i <= n; i++)
			{
				res += n - 2*a[i-1] + 1;
				if(res < ans) ans = res;
			}
			printf("%d\n", ans);
		}
	}

	~MinimumInversionNumber_3_TreeArray()
	{
		free(a);
		free(c);
	}
};

hdu1394 树状数组 解法

时间: 2024-07-28 22:17:16

hdu1394 树状数组 解法的相关文章

HDU 1754 树状数组 解法

mnesia在频繁操作数据的过程可能会报错:** WARNING ** Mnesia is overloaded: {dump_log, write_threshold},可以看出,mnesia应该是过载了.这个警告在mnesia dump操作会发生这个问题,表类型为disc_only_copies .disc_copies都可能会发生. 如何重现这个问题,例子的场景是多个进程同时在不断地mnesia:dirty_write/2 mnesia过载分析 1.抛出警告是在mnesia 增加dump

Poj 2299 Ultra-QuickSort 树状数组 解法

本题的树状数组稍微有点特点,就是需要所谓的离散化一下,开始听这个名称好像很神秘的,不过其实很简单. 就是把一个数组arr的值,其中的值是不连续的,变成一组连续的值,因为这样他们的顺序是不变的,所以,不影响结果. 例如:9 1 0 5 4 ->变为:5 2 1 4 3看出他们的相对位置不变的. 9和5为最大值在第一个位置,1和2为第二大的值在第二个位置,0和1在第一个位置等,看出对应顺序了吗? 对,就是这么简单的方法, 就叫做离散化. 如果你对counting sort熟悉的话,那么这样的思想理解

uva 12356 Army Buddies 树状数组解法 树状数组求加和恰为k的最小项号 难度:1

Nlogonia is fighting a ruthless war against the neighboring country of Cubiconia. The Chief General of Nlogonia's Army decided to attack the enemy with a linear formation of soldiers, that would advance together until conquering the neighboring count

poj 2481 Cows 树状数组解法,详细解析。

Cows Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 13445   Accepted: 4448 Description Farmer John's cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one-dimensional number line) in hi

poj 2299 Ultra-QuickSort 求逆序数,树状数组解法,详细解析

Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 44554   Accepted: 16195 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swappin

tyvj P1716 - 上帝造题的七分钟 二维树状数组区间查询及修改 二维线段树

P1716 - 上帝造题的七分钟 From Riatre    Normal (OI)总时限:50s    内存限制:128MB    代码长度限制:64KB 背景 Background 裸体就意味着身体. 描述 Description “第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵.第二分钟,L说,要能修改,于是便有了将左上角为(a,b),右下角为(c,d)的一个矩形区域内的全部数字加上一个值的操作.第三分钟,k说,要能查询,于是便有了求给定矩形区域内的全部数字和的操作.第

Poj 2182-Lost Cows(Treap||树状数组+二分答案)

题目链接:点击打开链接 题意:n个牛编号为1-n 现在编号顺序已经打乱,给出a[i] ,a[i] 代表i位置前面有几个小于它的编号,求编号顺序. 倒着推,对于最后一个a[i] , 最后位置编号肯定是 a[i]+1,然后在1-n个编号中删掉当前编号,继续往前推..即求第 a[i]+1小数,初始容器中有n个数(1-n) ,每求出来一个就删掉.先用平衡树水了一发..明天写树状数组解法. #include <algorithm> #include <iostream> #include &

HDU 1166 敌兵布阵 (线段树 &amp; 树状数组)

敌兵布阵 Time Limit:1000MS    Memory Limit:32768KB    64bit IO Format:%I64d & %I64u SubmitStatus 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的

POJ 2761 Feed the dogs(树状数组求区间第K大)

题目链接: 戳我 题目大意:Jiajia要为宠物狗,宠物狗按成一排站好(1 < i <= n),第 i 只狗的喜欢程度是 a[i], 之后他会先喂某个区间内第k个 即 n 个数, m个询问,接着是 n个数 接下来 m 行,每行是 l r k即 l 到 r 这个区间第 k 小的数,每个询问输出一个答案,即 a[i] 求区间第k大有很多算法, 详见此博客 [数据结构练习] 求区间第K大数的几种方法 我用的树状数组解法,来自 树状数组从前往后求和,用来解第k大(或小)的数 poj 2985 The