LA4329 Ping pong(树状数组)

来源:互联网 发布:演唱会抢票攻略 知乎 编辑:程序博客网 时间:2024/05/16 12:52

题目链接

一群乒乓爱好者组织比赛,给出一群乒乓爱好者的技能值,每场比赛需要两名选手和一名裁判。裁判必须在选手中间,并且技能值也在选手中间,问一共能组织多少种比赛?

选手的技能值:A1······Ai······An;

假设在A1到Ai内有c个选手的技能值比Ai小,即有(i-1-c)个选手的技能值比Ai大;

假设在Ai到An内有d个选手的技能值比Ai小,即有(n-i-d)个选手的技能值比Ai大;

所以,总共的方案个数:c*(n-i-d)+(i-1-c)*d;

代码如下:

#include <iostream>#include <stdio.h>#include <string.h>using namespace std;const int N=200005;int n;long long tree[N];int t;int data[N];long long pre[N];long long sub[N];int lowbit(int i){    return i&(-i);}void update(int i,int x){    while(i<=N)    {        tree[i]+=x;        i+=lowbit(i);    }}int query(int i){    int ans=0;    while(i>0)    {        ans+=tree[i];        i-=lowbit(i);    }    return ans;}int main(){    scanf("%d",&t);    while(t--)    {        memset(tree,0,sizeof(tree));        memset(pre,0,sizeof(pre));        memset(sub,0,sizeof(sub));        scanf("%d",&n);        for(int i=1;i<=n;i++)            scanf("%d",&data[i]);        for(int i=1;i<=n;i++)        {            pre[i]=query(data[i]-1);            update(data[i],1);        }        memset(tree,0,sizeof(tree));        for(int i=n;i>=1;i--)        {            sub[i]=query(data[i]-1);            update(data[i],1);        }        long long ans=0;        for(int i=1;i<=n;i++)        {            long long c=pre[i];            long long d=sub[i];            ans+=c*(n-i-d)+(i-1-c)*d;        }        printf("%lld\n",ans);    }    return 0;}


原创粉丝点击