给你N的一个排列,求满足:a[i] < a[k] < a[j] 并且i < j < k的三元组有多少个。
一步转化:
求出所有满足 a[i] < a[k] < a[j] 并且i < j < k的三元组 与 a[i] < a[k] < a[j] 并且i < k < j的三元组 的个数的总和,设high[i]为在 i 右侧且大于a[i] 的数的个数,上述总和即为:high[i] * (high[i] - 1) / 2。
设low[i]为在 i 左侧且小于a[i] 的数的个数, a[i] < a[k] < a[j] 并且i < k < j的三元组 的个数即为:low[i]*high[i]。
答案即为:∑( high[i] * (high[i] - 1) / 2 - low[i]*high[i] );
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <algorithm> 5 6 #define LL long long int 7 8 using namespace std; 9 10 const int MAXN = 100100; 11 const LL MOD = 100000007; 12 13 int N; 14 int C[MAXN]; 15 int num[MAXN]; 16 int low[MAXN]; 17 int high[MAXN]; 18 19 int lowbit( int x ) 20 { 21 return x & ( -x ); 22 } 23 24 void Update( int x, int val ) 25 { 26 while ( x <= N ) 27 { 28 C[x] += val; 29 x += lowbit(x); 30 } 31 return; 32 } 33 34 int Query( int x ) 35 { 36 int res = 0; 37 while ( x > 0 ) 38 { 39 res += C[x]; 40 x -= lowbit(x); 41 } 42 return res; 43 } 44 45 int main() 46 { 47 int T, cas = 0; 48 scanf( "%d", &T ); 49 while ( T-- ) 50 { 51 scanf( "%d", &N ); 52 for ( int i = 1; i <= N; ++i ) 53 scanf( "%d", &num[i] ); 54 55 memset( C, 0, sizeof(C) ); 56 57 for ( int i = 1; i <= N; ++i ) 58 { 59 low[i] = Query( num[i] - 1 ); 60 Update( num[i], 1 ); 61 } 62 63 memset( C, 0, sizeof(C) ); 64 for ( int i = N; i > 0; --i ) 65 { 66 //printf("i=%d %d %d ", i, Query( N ), Query( num[i] ) ); 67 high[i] = Query( N ) - Query( num[i] ); 68 Update( num[i], 1 ); 69 } 70 71 LL ans = 0; 72 for ( int i = 1; i <= N; ++i ) 73 { 74 //printf( "h=%d l=%d ", high[i], low[i] ); 75 ans += (LL)high[i] * ( high[i] - 1 ) / 2 - (LL)low[i] * high[i]; 76 ans = ( ans + MOD ) % MOD; 77 } 78 79 printf( "Case #%d: %I64d ", ++cas, ans % MOD ); 80 } 81 return 0; 82 }