蓝桥杯 小朋友排队

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

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

还是先看清楚数据量啊!

#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;
}

 

posted @ 2015-03-11 13:14  UsedRose  阅读(327)  评论(0编辑  收藏  举报