hdu4000-树状数组-2

来源:互联网 发布:文明5 mac 迅雷 编辑:程序博客网 时间:2024/06/05 13:55

 http://acm.hdu.edu.cn/showproblem.php?pid=4000

题意:对1--n的一个排列,求所有的i<j<k且a[i]<a[k]<a[j]的个数。。。

 

分析:比赛的时候总是想不出来怎么做,老想着单纯枚举i或者j或者k来求得结果,不知道变通。。。实际上可以换个方向思考,对每个位置考虑后面有多少比他大的数,则这个小的后面跟两个大的个数为x(x-1)/2,然后肯定要减去后面的所有组成的i<j<k且a[i]<a[j]<a[k]的个数,这两种操作都可以解决,则问题就转化为扫描一遍数组而已了。。。

 

代码:

#include <stdio.h>#include <iostream>using namespace std;const int N=100001;int a, n, f[N];__int64 ans, tmp, tmp1;void insert(int i){for(; i<=n; i+=i&(-i))f[i] += 1;}int query(int i){int tmp=0;for(; i>0; i-=i&(-i))tmp += f[i];return tmp;}int main(){int i, cas, cas1=1;scanf("%d", &cas);while(cas--){scanf("%d", &n);ans = 0;for(i=1; i<=n; i++)f[i] = 0;for(i=1; i<=n; i++){scanf("%d", &a);insert(a);tmp = query(a-1);tmp1 = (n-a)-(i-1-tmp);ans -= tmp*tmp1;if(tmp1>=2)ans += tmp1*(tmp1-1)/2;}printf("Case #%d: %I64d\n", cas1++, ans%100000007);}return 0;}


 

原创粉丝点击