POJ3928、LA4329【树状数组】

借此题试验一下各种做法的效果~

这题为ACM2008北京站某题,介于简单与中等之间,做出来,罚时不多基本可以铜了,所以这样的题还必须得会,进阶之路。

add(a[i]+1,1)这样处理之后,再用sum(a[i])计算得出的便的确是比a[i]小的数目。结合树状图进一步了解下。

树状数组异常的美妙~

 

add(a[i],1)后树状数组的改变或许很复杂。。

 

嗯嗯!!明白了。

 

若换成add(a[i],1)后结果要相应换为sum(a[i])-1;就相当于在a[i]处多加了1,后面的就相当于add(a[i]+1,1)呗~~,但耗时会增多30+MS

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
const int maxn=100005;
long long  c[maxn];
int a[20005];
long long temp[maxn];
int lowbit(int x)
{
    return x&-x;
}
void add(int x,int y)
{
    while(x<=maxn)
    {
       c[x]+=y;
       x+=lowbit(x);
    }
}
long long sum(int x)
{
    long long ret=0;
    while(x>0)
    {
        ret+=c[x];
        x-=lowbit(x);
    }
    return ret;
}
int main()
{
    int case_num;
    scanf("%d",&case_num);
    while(case_num--)
    {
        memset(c,0,sizeof(c));
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            add(a[i]+1,1);//自己再试一下只能0 1值的数组,结果类似,把+1换成+x[i]
            temp[i]=sum(a[i]);//这地方减c[x]对不对。。
        }
        long long ans=0;
        for(int i=1;i<=n;i++)
           printf(" %d ",sum(a[i]));
        printf("\n");
        for(int i=2;i<n;i++)
        {
            ans+=temp[i]*(n-i-(sum(a[i])-temp[i]));//其实一开始sum(a[i])-temp[i]还不太确定
            ans+=(i-1-temp[i])*(sum(a[i])-temp[i]);//我这个sum(a[i])到底包括本身不(不包括)
        }
        printf("%lld\n",ans);
    }
    return 0;
}


 


 

 

posted @ 2013-08-05 18:52  javawebsoa  Views(184)  Comments(0Edit  收藏  举报