HDU 5147 Sequence II (树状数组计数)

本文介绍了一个竞赛编程问题SequenceII的解决方案,该问题要求计算满足特定条件的四元组数量。通过使用树状数组进行有效的计数与统计,文章详细解释了解题思路与实现步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Sequence II

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1435    Accepted Submission(s): 596


 

Problem Description

Long long ago, there is a sequence A with length n. All numbers in this sequence is no smaller than 1 and no bigger than n, and all numbers are different in this sequence.
Please calculate how many quad (a,b,c,d) satisfy:
1. 1≤a<b<c<dn
2. Aa<Ab
3. Ac<Ad

 

 

Input

The first line contains a single integer T, indicating the number of test cases.
Each test case begins with a line contains an integer n.
The next line follows n integers A1,A2,…,An.

[Technical Specification]
1 <= T <= 100
1 <= n <= 50000
1 <= Ai <= n

 

 

Output

For each case output one line contains a integer,the number of quad.

 

 

Sample Input

 

1 5 1 3 2 4 5

 

 

Sample Output

 

4

 

 

Source

BestCoder Round #23

 

 

Recommend

heyang   |   We have carefully selected several similar problems for you:  6447 6446 6445 6444 6443 

 

#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define ll long long

const int  maxn =1e5+5;
const int mod=1e9+7;
///树状数组
int tree[maxn];
int lowbit(int x){return x&(-x);}
ll sum(int x){ll ret=0;for(;x>0;ret+=1LL*tree[x],x-=lowbit(x));return ret;}
void add(int x,int d){for(;x<maxn;tree[x]+=d,x+=lowbit(x));}

ll mark1[maxn],mark2[maxn];///记录数组
int a[maxn],n;
/*
题目大意:统计四元组,该四元组满足前两个数和后两个数按序号递增。

很明显树状数组维护,
首先思考如何唯一的计数一个四元组,
如果确定了第一个二元组的第二个数,那么包含这个数的四元组
就是前面比这个数小的数的个数*后面的二元组对数(大小关系)。

那么思路大致有了,先树状数组维护出来比当前数字小的前面的数字个数,
再类似的倒叙维护一遍,然后把倒叙维护出来的数组统计前缀和。
按序扫一遍计数答案就行了。
*/

int main()
{
    int t;scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);  for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        memset(tree,0,sizeof(tree));
        for(int i=1;i<=n;i++)
        {
            mark1[i]=sum(a[i]);
            add(a[i],1);
        }
        memset(tree,0,sizeof(tree));
        for(int i=n;i>=1;i--)
        {
            mark2[i]=sum(n)-sum(a[i]-1);
            add(a[i],1);
        }
        ll ans=0;   mark2[n+1]=0;
        for(int i=n;i>=1;i--) mark2[i]+=mark2[i+1];
        for(int i=1;i<=n;i++)  if(mark1[i]) ans+=1LL*mark1[i]*mark2[i+1];
        printf("%lld\n",ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值