LA 4329 Ping pong

来源:互联网 发布:nginx防止ddos攻击 编辑:程序博客网 时间:2024/06/05 15:32

题意:有n个兵乓球选手,每个人都有唯一的一个技能值,每场比赛需要一个裁判,这个裁判的技能值和标号都要在两个选手之间,问能够举办的比赛的种类。

思路:对于第i个人来说,如果可以求出在他左边比他技能值小的数量ai和在他右边比技能值比他小的人得数量bi,那么就可以分别算出左右两边比他技能值大的选手的数量ci和di,则当第i个人当裁判时,就有ai*di+bi*ci种比赛种类。由于技能值的范围比较小,求ai的时候可以从左到右扫描,计算在i前比它小的技能值的数量,计算方法可以使用树状数组求ai的前缀和(也可以用线段树),计算bi与ai同理,从右向左扫描即可。不过事实证明还是树状数组比较快啊,还比较好写。

 

代码:

 

树状数组实现:

#include <iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int maxn=100000+10;ll C[maxn],ci[maxn],di[maxn],num[maxn];int lowbit(int x){    return x&-x;}ll sum(int x){    ll ret=0;    while(x>0)    {        ret+=C[x];        x-=lowbit(x);    }    return ret;}void add(int x,int v,ll n){    while(x<=n)    {        C[x]+=v;        x+=lowbit(x);    }}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int t,n;    cin>>t;    while(t--)    {        cin>>n;        ll res=0;        ll maxnum=0;        for(int i=1;i<=n;++i)        {            cin>>num[i];            maxnum=max(maxnum,num[i]);        }        memset(C,0,sizeof(C));        for(int i=1;i<=n;++i)        {            add(num[i],1,maxnum);            ci[i]=sum(num[i])-1;        }        memset(C,0,sizeof(C));        for(int i=n;i>=1;--i)        {            add(num[i],1,maxnum);            di[i]=sum(num[i])-1;        }        for(int i=1;i<=n;++i)        {            res+=ci[i]*(n-i-di[i])+di[i]*(i-1-ci[i]);        }        cout<<res<<endl;    }    return 0;}


 

线段树实现:

#include <iostream>#include<cstdio>#include<cstring>#include<string>#include<algorithm>#include<map>#include<queue>#include<stack>#include<cmath>#include<vector>#define inf 0x3f3f3f3f#define Inf 0x3FFFFFFFFFFFFFFFLL#define eps 1e-9#define pi acos(-1.0)using namespace std;typedef long long ll;const int N=100000;const int maxn=(100000+10)<<1;const int maxm=20000+10;int C[maxn<<1],num[maxm],ci[maxm],di[maxm];void PushUp(int rt){    C[rt]=C[rt<<1]+C[rt<<1|1];}void build(int l,int r,int rt){    if(l==r)    {        C[rt]=0;        return;    }    int m=(l+r)>>1;    build(l,m,rt<<1);    build(m+1,r,rt<<1|1);    PushUp(rt);}int Query(int L,int R,int l,int r,int rt){    if(l>=L&&r<=R)    {        return C[rt];    }    int sum=0;    int m=(l+r)>>1;    if(m>=L)      sum+=Query(L,R,l,m,rt<<1);    if(m<R)      sum+=Query(L,R,m+1,r,rt<<1|1);    return sum;}void Update(int p,int l,int r,int rt){    if(l==r)    {        C[rt]+=1;        return;    }    int m=(l+r)>>1;    if(m>=p)      Update(p,l,m,rt<<1);    else      Update(p,m+1,r,rt<<1|1);    PushUp(rt);}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int t,n;    cin>>t;    while(t--)    {        cin>>n;        build(1,N,1);        ll res=0;        for(int i=1;i<=n;++i)        {            cin>>num[i];            Update(num[i],1,N,1);            //cout<<Query(1,num[i],1,N,1)<<endl;            ci[i]=Query(1,num[i],1,N,1)-1;        }        build(1,N,1);        for(int i=n;i>=1;--i)        {            Update(num[i],1,N,1);            di[i]=Query(1,num[i],1,N,1)-1;        }        for(int i=1;i<=n;++i)        {            res+=ci[i]*(n-i-di[i])+di[i]*(i-1-ci[i]);        }        cout<<res<<endl;    }    return 0;}