Poj 3828 Ping pong

来源:互联网 发布:gis开源软件 编辑:程序博客网 时间:2024/05/16 11:34

题目链接:http://poj.org/problem?id=3928

考虑第i个人当裁判的情形,假设a1到ai-1有ci个比ai小,那么就有(i-1)-ci个比ai大的;同理,假设ai+1 到an中有di个比ai小,那么就有n-i-di个比ai大。

这样最终i当裁判时有ci*(n-i-di) + (i-ci-1)*di中比赛。最后累加即可。

求ci的时候可以对计数下标进行树状数组实时求前缀和。关于后缀和di,可以逆序求解。

#include <stdio.h>#include <string.h>#include <math.h>#include <stdlib.h>#include <time.h>#include <vector>#include <set>#include <map>#include <algorithm>using namespace std;#define Maxn 100005int x[Maxn];//int a[20005];//原始数组int c[20005];//前缀和int d[20005];//后缀和int lowbit(int y){    return y&(-y);}int sum(int y){    int result = 0;    while(y>0)    {        result += x[y];        y -= lowbit(y);    }    return result;}int add(int y,int s){    while(y<=Maxn-1)    {        x[y] += s;        y += lowbit(y);    }}int main(){#ifndef ONLINE_JUDGE    freopen("in.txt", "r", stdin);#endif    int t;    int n;    long long ans = 0;    scanf(" %d",&t);    while(t--)    {        ans = 0;        scanf(" %d",&n);        memset(x,0,sizeof(x));        for(int i=1;i<=n;i++)        {            scanf(" %d",&a[i]);            c[i] = sum(a[i] - 1);            add(a[i],1);        }        memset(x,0,sizeof(x));        for(int i=n;i>=1;i--)        {            d[i] = sum(a[i] - 1);            add(a[i],1);        }        for(int i=1;i<=n;i++)        {            ans += (long long)c[i] * (n-i-d[i]) + (long long)(i-1-c[i])*d[i];        }        printf("%lld\n",ans);    }}


原创粉丝点击