歡迎訪問我的PAT頂級題解目錄
Given a list of N integers A1, A2, A3,...AN, there's a famous problem to count the number of inversions in it. An inversion is defined as a piar of indices i<j such that Ai>Aj.
Now we have a new challenging problem. You are supposed to count the number of triple inversions in it. As you may guess, a triple inversion is defined as a triple of indices i<j<k such that Ai>Aj>Ak. For example, in the list { 5, 1, 4, 3, 2 } there are 4 triple inversions, namely (5,4,3), (5,4,2), (5,3,2) and (4,3,2). To simplify the problem, the list A is given as a permutation of integers from 1 to N.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N in [3,105]. The second line contains a permutation of integers from 1 to N and each of the integer is separated by a single space.
Output Specification:
For each case, print in a line the number of triple inversions in the list.
Sample Input:
22
1 2 3 4 5 16 6 7 8 9 10 19 11 12 14 15 17 18 21 22 20 13
Sample Output:
8
題目大意:給出一個長爲n的序列(序列爲1-n的某種排列),求給定序列中有多少個三元遞減序列
解題思路:遍歷,將每個數看爲中間那個數字,只要求出該數左邊有多少比它大的數,右邊有多少比它小的數,兩個數目相乘即可。
left記錄該數左邊有多少比它大的數
right記錄右邊有多少比它小的數
樹狀數組
樹狀數組維護的C,C[i]表示原數組A中數組爲 i 出現了C[i]次
每次插入時,用樹狀數組的getNum查詢當前(該數左邊)有多少比它小的數,,通過簡單的運算就可以算出left和right的值
#include <bits/stdc++.h>
#define lowbit(i) ((i) & (-i))
using namespace std;
const int maxn = 100010;
int c[maxn];
void update(int x, int val){
for(int i = x; i < maxn; i += lowbit(i))
c[i] += val;
}
int getSum(int x){
int ans = 0;
for(int i = x; i >= 1; i -= lowbit(i))
ans += c[i];
return ans;
}
int main(){
int n;
long long int left, right, ans = 0;
scanf("%d", &n);
vector<int> a(n);
for(int i = 0; i < n; ++ i){
scanf("%d", &a[i]);
update(a[i], 1);
left = i + 1 - getSum(a[i]);
right = a[i] - getSum(a[i] - 1) - 1;
ans += left * right;
}
printf("%lld", ans);
}
平衡二叉樹
我們的目的是要針對數組中某個數,求該數的左邊比它大的個數,右邊比他小的個數,時間代價儘可能小,除了樹狀數組,平衡樹也可以滿足我們的需求。
可以調用pb_ds庫,具體使用可以參考平板電視庫
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
using namespace std;
using namespace __gnu_pbds;
int main(){
tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> tr;
int n, temp;
long long int left, right, ans = 0;
scanf("%d", &n);
for(int i = 0; i < n; ++ i){
scanf("%d", &temp);
tr.insert(temp);
left = i - tr.order_of_key(temp);
right = temp - tr.order_of_key(temp) - 1;
ans += left * right;
}
printf("%lld", ans);
}