HDU2838Cow Sorting(树状数组)
题目意思是说给你一列数,每次可以将相邻的两个数交换,这一步的代价是这两个数的和,求将所有数排好序的最少代价。
题解:
我们可以这么思考,由于每次都是交换相邻的两个数,所以将一个数放到它自己的位置去后,其他的数的相对位置没变,那么排序其他的数所需要消耗的代价将与这个数没关系,所以排序过程将相当于是冒泡排序。
这样的话我们用树状数组可以记录第i个数之前有多少个比它小的的数x
再记录这些比它小的数的和是多少sum
然后这个数移动到他自己的位置的代价就是
x*a[i]+sum。
最后的复杂度就是nlogn
以后排序和求和的题应该多想想树状数组~恩恩
1 #include <map> 2 #include <set> 3 #include <stack> 4 #include <queue> 5 #include <cmath> 6 #include <ctime> 7 #include <vector> 8 #include <cstdio> 9 #include <cctype> 10 #include <cstring> 11 #include <cstdlib> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 #define INF 0x3f3f3f3f 16 #define MAX(a,b) (a > b ? a : b) 17 #define MIN(a,b) (a < b ? a : b) 18 #define mem0(a) memset(a,0,sizeof(a)) 19 #define mem1(a) memset(a,-1,sizeof(a)) 20 #define lson k<<1, L, mid 21 #define rson k<<1|1, mid+1, R 22 23 typedef long long LL; 24 const double eps = 1e-12; 25 const int MAXN = 100005; 26 const int MAXM = 500005; 27 28 29 struct NODE 30 { 31 int num;//记录个数 32 __int64 sum;//记录比它小的数的和 33 }c[MAXN]; 34 int N; 35 36 void init() 37 { 38 mem0(c); 39 } 40 41 int lowbit(int x) 42 { 43 return x & (-x); 44 } 45 46 void edit(int k, int num) 47 { 48 while(k <= 100000) 49 { 50 c[k].num += 1; 51 c[k].sum += num; 52 k += lowbit(k); 53 } 54 } 55 56 int getnum(int k)//得到比当前数小的数的个数 57 { 58 int num = 0; 59 while(k > 0) 60 { 61 num += c[k].num; 62 k -= lowbit(k); 63 } 64 return num; 65 } 66 67 __int64 getsum(int k)//得到比当前数小的数的和 68 { 69 __int64 sum = 0; 70 while(k>0) 71 { 72 sum += c[k].sum; 73 k-=lowbit(k); 74 } 75 return sum; 76 } 77 78 int main() 79 { 80 while(~scanf("%d", &N)) 81 { 82 init(); 83 int num; 84 __int64 ans = 0; 85 for(int i=1;i<=N;i++) 86 { 87 scanf("%d", &num); 88 edit(num, num); 89 int cnt = i - getnum(num);//有cnt的数比num大 90 if(cnt != 0) 91 { 92 ans += (__int64)cnt*num + getsum(100000)-getsum(num); 93 } 94 } 95 printf("%I64d\n", ans); 96 } 97 return 0; 98 }