鏈接:
B. Mega Inversions
The n2 upper bound for any sorting algorithm is easy to obtain: just take two elements that are misplaced with respect to each other and swap them. Conrad conceived an algorithm that proceeds by taking not two, but three misplaced elements. That is, take three elements ai > aj > ak with i < j < k and place them in order ak, aj , ai. Now if for the original algorithm the steps are bounded by the maximum number of inversions n(n-1)/2 , Conrad is at his wits' end as to the upper bound for such triples in a given sequence. He asks you to write a program that counts the number of such triples.
Input
Output
Output the number of inverted triples.
Sample Input
Sample Input 1 3 1 2 3 Sample Input 2 4 3 3 2 1
Sample Output
Sample Output 1 0 Sample Output 2 2
算法:樹狀數組
題意:
思路:
以每一個數爲中間的數,在它前面找一個比它大的數,在它後面找一個比它小的數就形成了一個inverted triples
那麼題目就轉化成了,求出每一個數前面有多少個數比它小,記爲 ans1, 後面有多少個數比它大,記爲 ans2。
然後 ans1*ans2 就是以這個數爲中間的數的對應的 inverted triples的數目。
那麼只要求出每一個數前面有多少數比它大,後面有多少個數比它小
依次記錄後遍歷相乘的結果即爲所求。
注意:數據比較小,You can assume that all ai are in [1, n].
所以不用離散化。。。。比賽的時候求正序數對的時候各種離散化各種錯思路一下就明確了,代碼敲了一個小時還是各種錯。
如此弱菜我還能說什麼呢。
code:
#include<stdio.h>
#include<string.h>
const int maxn = 1e5+10;
int n;
int a[maxn]; //記錄每一個數
int c[maxn];
long long ans1[maxn];
long long ans2[maxn];
int lowbit(int x)
{
return x&(-x);
}
void add(int i)
{
while(i <= n)
{
c[i]++;
i += lowbit(i);
}
}
long long sum(int i)
{
long long ret = 0;
while(i > 0)
{
ret += c[i];
i -= lowbit(i);
}
return ret;
}
int main()
{
while(scanf("%d", &n) != EOF)
{
memset(a, 0, sizeof(a)); //清空
memset(c, 0, sizeof(c));
memset(ans1, 0, sizeof(ans1));
memset(ans2, 0, sizeof(ans2));
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
for(int i = 1; i <= n; i++)
{
ans1[i] = sum(n) - sum(a[i]); //計算出現在 a[i] 前面比 a[i] 大的數的個數:總數- <=a[i] 的數
add(a[i]); //插入當前數據
}
memset(c, 0, sizeof(c)); //重新清零
for(int i = n; i >= 1; i--) //逆序插入
{
ans2[i] = sum(a[i]-1); //計算出現在 a[i] 後面但是比 a[i] 小的數的個數
add(a[i]); //插入當前數據
}
long long ans = 0;
for(int i = 1; i <= n; i++)
ans += ans1[i]*ans2[i]; //前面比它大*後面比它小
printf("%lld\n", ans);
}
return 0;
}