蓝桥杯 小朋友排队 逆序对+树状数组


#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define MAX 1000005
#define MIN 100005
long long ans = 0; 
long long to[MIN];
int n;
int a[MIN];
int sum[MIN];
int c1[MAX];
int c2[MAX];

int lowbit(int x)
{
    return x&(-x);
}

void add(int pos,int val,int *c)
{
    while(pos <= MAX)
    {
        c[pos] += val;
        pos += lowbit(pos);
    }
}

int getsum(int pos,int *c)
{
    int sum = 0;
    while(pos > 0)
    {
        sum += c[pos];
        pos -= lowbit(pos);
    }
    return sum;
}

int main()
{
    scanf("%d",&n);
    memset(c1,0,sizeof c1);
    memset(c2,0,sizeof c2);
    for(int i = 1; i <= n;i++)
        to[i] = to[i-1]+i;
    for(int i = 1;i <= n;i++)
    {
        scanf("%d",&a[i]);
        add(a[i]+1,1,c1);
        sum[i] +=i - getsum(a[i]+1,c1); 
    }
    for(int i=n;i >=1;i--)
    {
        add(a[i]+1,1,c2);
        sum[i] +=getsum(a[i],c2); 
    }
    for(int i= 1;i <= n;i++)
        ans += to[sum[i]];
    printf("%ld",ans);
    
    return 0;
}
View Code

 

posted @ 2018-03-06 17:02  INER  阅读(140)  评论(0编辑  收藏  举报