当前位置: 代码迷 >> 综合 >> HDU 2492 - Ping pong
  详细解决方案

HDU 2492 - Ping pong

热度:14   发布时间:2023-12-13 03:53:55.0

题目描述

Ping pong

解法:树状数组(C++)

我们先来翻译一下题目思路就来了,原题的描述有点绕:

每三个人进行一场比赛,裁判只能处在两个选手之后,且裁判的能力值要大于其中一个选手,而小于另外一个选手

好了,这就是题意,按照排列组合,是不是对每个裁判的位置左边取一个能力小于其的选手,右边取一个能力大于其的选手,就构成了一场比赛;反过来,左边取一个能力大于其的选手,右边取一个能力小于其的选手,就又构成了一场比赛

是不是超简单 (。???)ノ

这里,树状数组用两次,一次处理 lleft[i]lleft[i]lleft[i],记录左边能力小于当前裁判位置的选手的个数;一次处理 rrightrrightrright,记录右边能力小于当前裁判位置的选手的个数

#include <iostream>
#include <string.h>using namespace std;const int N = 100005;
int T, n;
long long ans;
int a[20005], lleft[20005], c[N], rright;int lowbit(int x){
    return x&(-x);}void add(int x){
    for(int i=x;i<=N;i+=lowbit(i))c[i]++;
}int sum(int x){
    int s = 0;for(int i=x;i;i-=lowbit(i))s += c[i];return s;
}int main()
{
    scanf("%d", &T);while(T--){
    scanf("%d", &n);memset(c, 0, sizeof(c));for(int i=1;i<=n;i++){
    scanf("%d", &a[i]);add(a[i]);lleft[i] = sum(a[i]-1);}memset(c, 0, sizeof(c));ans = 0;for(int i=n;i;i--){
    add(a[i]);rright = sum(a[i]-1);ans += lleft[i]*(n-i-rright)+(i-1-lleft[i])*rright;}printf("%lld\n", ans);}return 0;
}