话说这道题要用的三个树状数组,不容易啊。我刚开始想的时候想明白了用公式怎么算,却想不出来怎么转化到树状数组上,总感觉有些地方实现不了,原来竟然是用三个树状数组。。。这让只写过一个树状数组的孩纸情何以堪?
具体来说,有一个num数组,里面记录的是插入a[i]后,在a[i]之前插入且比a[i]小的数的个数;还有一个totalsum数组,记录的是插入第i个数后,前i-1个数的总和;还有一个smallersum数组,记录的是插入a[i]后,在a[i]之前插入且比a[i] 小的数的总和。这样最后就可以算出来了。题目:
3 2 3 1
7HintInput Details Three cows are standing in line with respective grumpiness levels 2, 3, and 1. Output Details 2 3 1 : Initial order. 2 1 3 : After interchanging cows with grumpiness 3 and 1 (time=1+3=4). 1 2 3 : After interchanging cows with grumpiness 1 and 2 (time=2+1=3).
#include <cstdio> #include <stdlib.h> #include <string.h> #include <algorithm> using namespace std; const int M = 100010; __int64 num[M] , totalsum[M] , smallsum[M]; __int64 lowbit( __int64 x ) { return x&(-x); } void add( __int64 x[] , __int64 xx , __int64 yy ) { while( xx < M ) { x[xx] += yy; xx +=lowbit(xx); } } __int64 sum( __int64 x[] , __int64 xx ) { __int64 ss = 0; while( xx > 0 ) { ss += x[xx]; xx -= lowbit(xx); } return ss; } int main( ) { __int64 n; while( ~scanf("%I64d",&n) ) { memset( num , 0 , sizeof(num) ); memset( totalsum , 0 , sizeof(totalsum) ); memset( smallsum , 0 , sizeof(smallsum) ); __int64 x , ans = 0 , count = 0; for( __int64 i=1 ; i<=n ; i++ ){ scanf("%I64d",&x); add( num , x , 1 ); add( totalsum , i , x ); add( smallsum , x , x ); count = sum( num , x-1 ); ans += (i-count-1)*x; ans += sum(totalsum,i-1); ans -= sum(smallsum,x-1); } printf("%I64d\n",ans); } return 0; }