LA 4329(p197)----Ping pong

#include<bits/stdc++.h>
#define debu
using namespace std;
typedef long long LL;
const int maxn=2*1e4+50;
const int maxnn=1e5+50;
int a[maxn];
int n,l[maxn],maxx;
int c[maxnn],r[maxn];
inline int lowbit(int x)
{
    return x&(-x);
}
void add(int x,int value)
{
    for(int i=x; i<=maxx; i+=lowbit(i))
        c[i]+=value;
}
int sum(int x)
{
    int tmp=0;
    for(int i=x; i; i-=lowbit(i))
        tmp+=c[i];
    return tmp;
}
int main()
{
#ifdef debug
    freopen("in.in","r",stdin);
#endif // debug
    int t;
    scanf("%d",&t);
    while(t--)
    {
        maxx=0;
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
            maxx=max(maxx,a[i]);
        }
        LL ans=0;
        memset(c,0,sizeof(c));
        for(int i=1; i<=n; i++)
        {
            l[i]=sum(a[i]-1);
            //cout<<i<<" "<<l[i]<<endl;
            add(a[i],1);
        }
        memset(c,0,sizeof(c));
        for(int i=n; i>=1; i--)
        {
            r[i]=sum(a[i]-1);
            //cout<<i<<" "<<r[i]<<endl;
            add(a[i],1);
        }
        for(int i=1; i<=n; i++)
        {
       //     cout<<i<<" "<<l[i]<<" "<<r[i]<<endl;
            ans+=(long long)l[i]*(n-i-r[i])+(long long)r[i]*(i-1-l[i]);
          //  cout<<ans<<endl;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

题目地址:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2330

题解:对于第i个人,设在1到i-1有l[i]个人小于他则有i-1-l[i]大于他,同理i+1到n有r[i]人小于他,则有n-i-r[i]人大于他。由加法原理和乘法原理,ans=sigma(l[i]*(n-i-r[i])+r[i]*(i-1-l[i]),所以只需求出l[i]与r[i]:从前到后扫描,c[x]==1表示x存在,则l[i]=sigma(c[1],c[2],。。。。,(c[a[i]-1)),每求一次后c[a[i]]置为1,r[i]同理。

你可能感兴趣的:(LA 4329(p197)----Ping pong)