HDU5147 Sequence II && BestCoder Round #23 1002

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5147

题思路:BestCoder官方题解:

要统计四元组的数量我们可以通过枚举c,然后统计区间[1,c-1]有多少二元组(a,b)满足a
  
  
   
   <
  
  b且
  
  
   
   Aa<Ab
  
  ,以及统计出区间[c+1,n]有多少d满足
  
  
   
   Ac<Ad
  
  ,根据乘法原理,把这两项乘起来就可以统计到答案里了.
然后我们来处理子问题:区间[1,c-1]内有多少二元组(a,b).那么我们可以枚举b,然后统计区间[1,b-1]内有多少a满足
  
  
   
   Aa<Ab
  
  ,那么这个可以通过用树状数组询问前缀和来实现.
时间复杂度是O(nlogn).
AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

typedef __int64 ll;
int a[50010];
int n;

int lowbit(int x)
{
    return x&(-x);
}

int getsum(int x)
{
    int sum=0;
    while(x)
    {
        sum+=a[x];
        x-=lowbit(x);
    }
    return sum;
}

void add(int x)
{
    while(x<=n)
    {
        a[x]++;
        x+=lowbit(x);
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int i,m;
        ll pre=0,ans=0;
        memset(a,0,sizeof(a));
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&m);
            int t=getsum(m);
            int k=n-m-(i-t-1);//后面比m大的数字
            ans+=k*pre;
            pre+=t;
            add(m);
        }
        printf("%I64d\n",ans);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值