标签:
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5775
【题意】按照题目的冒泡排序求每个数在排序过程中到达最右边位置与最左边位置之差。
【解题思路】考虑i位置上的数字a[i]在冒泡排序过程的变化情况。a[i]会被其后面比a[i]小的数字各交换一次,之后a[i]就会只向前移动。数组从右向左扫,树状数组维护一下得到每个值右边有多少个比其小的值,加上原位置得到最右位置,最左位置为初始位置和最终位置的最小值。
【时间复杂度】O(n lg n)O(n\ lg\n)O(n lg n) (ps:其实我不会算复杂度……参考别人的)
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> using namespace std; const int maxn=100000+9; int n,ans[maxn],a[maxn],b[maxn],c[maxn]; //b[i]储存第i个元素右边有几个比它小的元素,ans[i]记录数字i对应的答案 int lowbit(int x) { return x&-x; } void update(int x) { while(x<=n) { c[x]++; x+=lowbit(x); } } int query(int x) { int ans=0; while(x>0) { ans+=c[x]; x-=lowbit(x); } return ans; } int main() { int T; cin>>T; for(int k=1;k<=T;k++) { cin>>n; memset(c,0,sizeof(c)); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=n;i>0;i--) { b[i]=query(a[i]); update(a[i]); } for(int i=1;i<=n;i++) ans[a[i]]=i+b[i]-min(i,a[i]); printf("Case #%d:",k); for(int i=1;i<=n;i++) printf(" %d",ans[i]); cout<<endl; } return 0; }
树状数组看了好久才明白OTZ
参考博客:http://blog.csdn.net/just_sort/article/details/52058551
hdu 5775 Bubble Sort 树状数组+冒泡排序
标签:
原文地址:http://www.cnblogs.com/dreamer-acm/p/5754150.html