树状数组 ( 求逆序数 )——Bubble Sort ( HDU 5775 ) ( 2016 Multi-University Training Contest 4 1012 )
2016-07-28 20:05
525 查看
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5775
分析:
给出N个数,将这几个数进行题中所述的“冒泡排序”,求每个数在排序过程中(包括始末状态)所达到的坐标的最大差值。
题解:
①我们可以先求出每个数在排序过程中所能达到最靠后的位置 loc ,然后 loc - min ( 起始点,终止点 ) 就是要求的最大差值。
②而每个点能移动到的最靠后的位置 loc 可以这样求:每个数前面比它大的数的个数 + 这个数的最终位置(可以通过找规律发现)。
③每个数前面比它大的数 即 逆序数 可以通过树状数组求得:
AC代码:
http://acm.hdu.edu.cn/showproblem.php?pid=5775
分析:
给出N个数,将这几个数进行题中所述的“冒泡排序”,求每个数在排序过程中(包括始末状态)所达到的坐标的最大差值。
题解:
①我们可以先求出每个数在排序过程中所能达到最靠后的位置 loc ,然后 loc - min ( 起始点,终止点 ) 就是要求的最大差值。
②而每个点能移动到的最靠后的位置 loc 可以这样求:每个数前面比它大的数的个数 + 这个数的最终位置(可以通过找规律发现)。
③每个数前面比它大的数 即 逆序数 可以通过树状数组求得:
int n;//一共多少个数 int c ; int Lowbit(int x) { return x & (-x); } void Update(int t,int val) { for(int i=t; i<=n; i+=Lowbit(i)) c[i] += val; } int getSum(int x) { int ans=0; for(int i=x; i>0; i-=Lowbit(i)) ans += c[i]; return ans; } //题解如下: for(int i=1;i<=n;i++) { Update(a[i], 1); int x = i - getSum(a[i]);//逆序数个数(a[i]之前大于a[i]数目的个数) int loc = x + a[i];//最远位置 int ans = loc - min(a[i], i);//a[i]的最大差值 b[a[i]] = ans; //存入答案数组 }
AC代码:
#include <cstdio> #include <iostream> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <cctype> #include <string> #include <map> #include <set> #include <queue> using namespace std; typedef pair<int,int> Pii; typedef long long LL; typedef unsigned long long ULL; typedef double DBL; typedef long double LDBL; #define MST(a,b) memset(a,b,sizeof(a)) #define CLR(a) MST(a,0) #define Sqr(a) ((a)*(a)) #define N 112345 int n; int c ; int a ; int Lowbit(int x) { return x & (-x); } void Update(int t,int val) { for(int i=t; i<=n; i+=Lowbit(i)) c[i] += val; } int getSum(int x) { int ans=0; for(int i=x; i>0; i-=Lowbit(i)) ans += c[i]; return ans; } int b ; int main() { int T; int tt = 1; scanf("%d", &T); while(T--) { CLR(c); CLR(b); scanf("%d", &n); for(int i=1;i<=n;i++) { scanf("%d", &a[i]); } for(int i=1;i<=n;i++) { Update(a[i], 1); int x = i - getSum(a[i]); int loc = x+a[i]; int ans = loc - min(a[i], i); b[a[i]] = ans; } printf("Case #%d: ", tt++); for(int i=1;i<n;i++) printf("%d ", b[i]); printf("%d\n", b ); } }
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- C#递归算法之分而治之策略
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- C#算法之大牛生小牛的问题高效解决方法
- C#算法函数:获取一个字符串中的最大长度的数字
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- 经典排序算法之冒泡排序(Bubble sort)代码
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法