POJ3928

对于原数据a[],树状数组c[],c[n]表示的段是c[n]=a[n-2^k+1]+....a[n],其中k是n在二进制下末尾0的个数,比如n=6(110)对于的k就是1;
//树状数组来做;
#include <iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=100005;
const int maxm=20005;
int  c[maxn];
int  rank1[maxm];
int  d[maxn];
int left1[maxm];
int right1[maxm];
int n;
int lowbit(int x)
{
    return (x&-x);
}
void update(int x,int c1)
{
    int i;
    //cout<<"hah"<<" ";
    for(i=x;i<=n;i+=lowbit(i))
    {
        c[i]+=c1;
    }

}
int getsum(int x)
{
    int i;
    int ans=0;
    for(i=x;i>0;i-=lowbit(i))
    {
        ans+=c[i];
    }
    return ans;
}
int main()
{
    int case1;
    scanf("%d",&case1);
    while(case1--)
    {
        memset(c,0,sizeof(c));
        int i;
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            scanf("%d",&rank1[i]);
            d[rank1[i]]=i;
        }
        sort(rank1,rank1+n);//这一步也很关键

        for(i=0;i<n;i++)
        {
            rank1[i]=d[rank1[i]]+1;
        }
        memset(left1,0,sizeof(left1));
        memset(right1,0,sizeof(right1));
        for(i=0;i<n;i++)
        {
           // cout<<"haha"<<endl;
            left1[i]=getsum(rank1[i]);//这一步是关键
            update(rank1[i],1);
        }
        //cout<<121<<endl;
        memset(c,0,sizeof(c));
        for(i=n-1;i>=0;i--)
        {
            right1[i]=getsum(rank1[i]);
            update(rank1[i],1);
        }
        long long ans=0;
        for(i=0;i<n;i++)
        {
            ans+=left1[i]*(n-i-1-right1[i])+(i-left1[i])*right1[i];
        }
        printf("%lld\n",ans);

    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值