蓝桥杯 历届试题 小朋友排队

这道题一开始推了很久 不知道怎么写 早就知道这道题是逆序数 但是这个不高兴怎么计算我确实找了好久
可惜最后还是没有找出来 我以为会是2*n+1(n是逆序数) 的这种规律
我好天真的
又!看了题解 有时候我也不想看题解的 真的不好
但是我实在推不出来 也没有办法了 唉

就是求这个数前面比它大 后面比她小的数
求法很简单 树状数组 线段树 归并排序 都可以
nlgn复杂度
这里的b,c几个数组我是为了方便 直观一点 其实可以不用的
这道题可以不使用离散化 但是数组要开一点 不然RE

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
int n;
const int maxn=100005;
int in[maxn];
int coun;
ll s[maxn];
int a[maxn];
ll b[maxn];
int temp[maxn];
ll c[maxn];
void updata(int x){
    while(x){
        s[x]++;
        x-=x&(-x);
    }
}
int calc(int x){
    int sum=0;
    while(x<=n){
        sum+=s[x];
        x+=x&(-x);
    }
    return sum;
}
bool cmp(int aa,int bb){
    return aa<bb;
}
int main(){
// freopen("int1.txt","r",stdin);
    while(scanf("%d",&n)!=-1){
        for(int i=0;i<n;i++){
            scanf("%d",&in[i]);

            temp[i]=in[i];
        }
        sort(in,in+n,cmp);
        coun=unique(in,in+n)-in;///size为离散化后元素个数
        for(int i=0;i<n;i++)
            a[i]=lower_bound(in,in+coun,temp[i])-in + 1;///k为b[i]经离散化后对应的值
        memset(s,0,sizeof(s));
        ll ans=0;
        for(int i=0;i<n;i++){
            b[i]=(ll)calc(a[i]+1);
            updata(a[i]);
        }
        memset(s,0,sizeof(s));
        for(int i=n-1;i>=0;i--){
            c[i]=(ll)(n-1-i-calc(a[i]));
            updata(a[i]);
        }
        for(int i=0;i<n;i++){
            b[i]=(ll)(c[i]+b[i]);
            ans+=(ll)((b[i]*(b[i]+1))>>1);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

你可能感兴趣的:(蓝桥杯 历届试题 小朋友排队)