题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4000
题目大意:求满足下列条件数的对数:i < j < k && ai < ak < aj
算法:线段树
思路:求大于ai 的数的个数ni,sum = ∑( ni * (ni-1) / 2) ),;再减去类似如下情况的数 1,3,4(即三个数从小到大排列的数的个数),方法见http://blog.csdn.net/zssee33/article/details/7925529。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
#define lson l, m, rt << 1
#define rson m+1, r, rt << 1 | 1
#define mid int m = (l+r) >> 1
int p[456456], cnt[456456];
void update(int k, int l , int r, int rt)
{
cnt[rt] ++;
if(l == r)
{
return ;
}
mid ;
if(k <= m)
update(k, lson);
else update(k, rson);
}
int query(int k, int l, int r, int rt)
{
if(l == r)
return cnt[rt];
mid ;
if(k <= m)
return query(k, lson);
else return cnt[rt << 1] + query(k, rson);
}
int main()
{
int T, n;
scanf("%d", &T);
int ica = 1;
while(T --)
{
scanf("%d", &n);
printf("Case #%d: ", ica ++);
int i;
memset(cnt, 0, sizeof(cnt));
__int64 sum = 0;
for(i = 1; i <= n; i ++)
{
scanf("%d", &p[i]);
__int64 k = query(p[i], 1, n, 1);
update(p[i], 1, n, 1);
__int64 b = n - p[i] - i + 1 + k;
sum -= k * b;
sum += (b) * (b-1) / 2;
}
printf("%I64d\n", sum % 100000007);
}
return 0;
}