hdu 4000 树状数组

来源:互联网 发布:网络运营课程 编辑:程序博客网 时间:2024/04/28 00:32

在1到n的序列中找满足val[a] < val[c] < val[b],其中(a < b < c)http://acm.hdu.edu.cn/showproblem.php?pid=4000


做题过程:

        我感觉树状数组都是那种先插小的,然后统计一下的那种。这题是求有多少个那样的折线。。。我开始有点蒙。哎,决定多想会,留到明天做。

今天是明天了。

       这题还是个逆向思维,正着弄不出来就逆着弄。


       对于一点x来说,先去找x后面比x大的有bb个(这个可以通过x前面比她小的fs求出来),那么,我们可以求出1,2这两种情况的总和sum。

       然后我们再去找1这样的情况有多少种,从sum里面减去就行了。情况为在x前面比x小的fs,在x后面比x大的bb,这两个数相乘。

/*Pro: 0Sol:date:*/#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>#include <cmath>#include <queue>#include <set>#include <vector>#define maxn 100100#define mod 100000007using namespace std;int t,n,c[maxn],val,ca;__int64 ret,fs,bb;void modify(int pos, int val){    while(pos <= n){        c[pos] += val;        pos += (pos & -pos);    }}int getsum(int pos){    int sum = 0;    while(pos){        sum += c[pos];        pos -= (pos & -pos);    }return sum;}void solve(){    memset(c,0,sizeof(c));    ret = 0;    scanf("%d",&n);    for(int i = 1; i <= n; i ++){        scanf("%d",&val);        modify(val,1);        fs = getsum(val - 1) % mod;//在val前面比val小的        bb =( ( n - i ) - ( val - 1 - fs ) ) % mod; //在val后面比val大的,后面有多少数,减去比她小的数        if(bb >= 2)//这个很重要!,因为bb为0的时候就麻烦了。            ret += ( (bb * (bb - 1) / 2)% mod);        ret -= (fs * bb % mod);        ret = (ret % mod + mod) % mod;    }    printf("Case #%d: %I64d\n",ca,(ret % mod + mod) % mod);}int main(){    scanf("%d",&t);    for(ca = 1; ca <= t; ca ++){        solve();    }return 0;}


原创粉丝点击