蓝桥杯 小朋友排队

。。。一开始傻傻暴力的。。

后来才知道是树状数组求逆序数。。

还是先看清楚数据量啊!

#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<cstring>

#include<string>

#include<queue>

#include<algorithm>

#include<map>

#include<iomanip>

#include<climits>

#include<string.h>

#include<cmath>

#include<stdlib.h>

#include<vector>

#include<stack>

#include<set>

using namespace std;

#define INF 1000000007

#define MAXN 4010

#define Mod 1000007

#define N 100010

#define NN 30

#define sigma_size 3

const int MAX = 1000100;

const int maxn = 6e5 + 10;

using namespace std;

typedef long long LL;





LL total[N], ans;

int num[N], C[MAX], S[MAX], b[N];

int lowbit(int x)

{

    return x&(-x);

}



void add(int pos,int num,int *p)

{

    while (pos <= MAX) {

        p[pos] += num;

        pos += lowbit(pos);

    }

}



int sum(int end, int *p)

{

    int cnt = 0;

    while (end > 0) {

        cnt += p[end];

        end -= lowbit(end);

    }

    return cnt;

}



void init()

{

    total[0] = 0;

    for (int i = 1; i < N; ++i) {

        total[i] = total[i - 1] + i;

    }

}



int main()

{

    int t;

    init();

    while (cin >> t){

        for (int j = 0; j < t; ++j){//因为第一个数前面比它小的数没有,所以j要从0开始

            cin >> num[j];

            add(num[j] + 1, 1, C);

            b[j] = j - sum(num[j], C);;//Sum(num[j],C)求的就是小于num[j]的个数,j - Sum(num[j],C)就是前j个数中大于num[j]的个数  

            b[j] -= sum(num[j] + 1, C) - sum(num[j], C) - 1;//不包括本身这个数

        }

        ans = 0;

        for (int j = t - 1; j > -1; --j) {//反过来求第j个数右边中小于它的数的个数

            add(num[j] + 1, 1, S);

            b[j] += sum(num[j], S);//sum(num[j],S)求的就是小于num[j]的个数

            ans += total[b[j]];

        }

        cout << ans << endl;

    }

    return 0;

}

 

你可能感兴趣的:(蓝桥杯)