UVa 1428 - Ping pong

传送门

UVa 1428 - Ping pong

题意

一条大街上住着N个人,每个人有不同的技能值,每场比赛要3个人,其中裁判要住在两个人中间,技能值也要在两人之间,求有多少种比赛方案。

思路

枚举裁判,统计出裁判左边比裁判技能值小的,技能值大的,右边。。。。。然后乘起来相加。

参考了别人的代码,熟悉了一下树状数组。

代码

#include <bits/stdc++.h>
#define LL long long
#define lowbit(x) ((x) & (-x))
#define MP(a, b) make_pair(a, b)
using namespace std;
const int MAXN = 2e4 + 5;
const int NMAXN = 1e5 + 5;
const int INF = 0x3f3f3f3f;
 
int a[MAXN], L[MAXN], R[MAXN], x[NMAXN], nmax;
 
int Sum(int num)
{
    int ret = 0;
    while (num > 0)
    {
        ret += x[num];
        num -= lowbit(num);
    }
    return ret;
}
 
void Add(int num)
{
    while (num <= nmax)
    {
        x[num]++;
        num += lowbit(num);
    }
}
 
int main()
{
    //freopen("input.txt", "r", stdin);
    int n, i, j, T;
    scanf("%d", &T);
    while (T--)
    {
        while (~scanf("%d", &n))
        {
            nmax = -1;
            for (i = 1; i <= n; i++)
            {
                scanf("%d", &a[i]);
                nmax = max(nmax, a[i]);
            }
            memset(x, 0, sizeof x);
            for (i = 1; i <= n; i++)
            {
                Add(a[i]);
                L[i] = Sum(a[i] - 1);
            }
            memset(x, 0, sizeof x);
            for (i = n; i >= 1; i--)
            {
                Add(a[i]);
                R[i] = Sum(a[i] - 1);
            }
            LL ans = 0;
            for (i = 1; i <= n; i++)
                ans += L[i] * (n - i - R[i]) + (i - L[i] - 1) * R[i];
            printf("%lld\n", ans);
        }
    }
    return 0;
}

Powered by Jekyll and Theme by solid