hdoj 2492

I hate Ping Pong!

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2492

题意:

有一坨人排成一条直线,每个人都有一个技能等级,有天他们想互相比试一下,a与b比试,c做裁判,规则如下:

1.c的位置必须在a、b之间;

2.c的技能等级必须在a、b之间。

思路:

以每个裁判为单位,可推出公式:裁判左边技能等级小于他的人数 * 裁判右边技能等级大于他的人数 = 该裁判所进行的比赛次数

所以可以通过两次树状数组,一次从左插入,一次从右插入来得出答案。

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define lowbit(x) x & (-x)
const int M = 20020;
const int S = 100020;
int tree[S], n, v[M], leftlower[M], leftupper[M], rightlower[M], rightupper[M];
void add(int a)
{
    while(a <= S)
    {
        tree[a]++;
        a += lowbit(a);
    }
}
int sum(int a)
{
    int total = 0;
    while(a > 0)
    {
        total += tree[a];
        a -= lowbit(a);
    }
    return total;
}
main()
{
    int T;
    cin >> T;
    while(T--)
    {
        cin >> n;
        for(int i = 1; i <= n; i++)
            scanf("%d", &v[i]);
        memset(tree, 0, sizeof(tree));
        for(int i = 1; i <= n; i++)
        {
            add(v[i]);
            leftlower[i] = sum(v[i] - 1);
            leftupper[i] = sum(S - 1) - sum(v[i]);
        }
        memset(tree, 0, sizeof(tree));
        for(int i = n; i >= 1; i--)
        {
            add(v[i]);
            rightlower[i] = sum(v[i] - 1);
            rightupper[i] = sum(S - 1) - sum(v[i]);
        }
        long long res = 0;
        for(int i = 1; i <= n; i++)
            res += (long long)rightlower[i] * leftupper[i] + (long long)rightupper[i] * leftlower[i];
        cout << res << endl;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值