【洛谷P1774】最接近神的人

最接近神的人_NOI导刊2010提高(02)

用类似于桶的方法,树状数组记录原序列的某位置之前已经插入了多少个数,

插入时树状数组单点加1即可

先排一遍序,从大到小插入所有数在原序列的位置,

统计每次插入时,在该元素前面元素的个数,

前面的元素是先插入的,比该元素大,而在序列中的位置靠前,

所以这个前缀和是逆序对数

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
#define int long long
#define lowbit(x) ((x)&(-(x)))
#define MAXN 500020
inline int read(){
    int x=0,f=1; char c=getchar();
    while(c<'0'||c>'9') { if(c=='-') f=-1; c=getchar(); }
    while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); }
    return x*f;
}
int n,tree[MAXN<<2];
struct NODE{
    int pos,value;
} x[MAXN];
inline bool cmp(NODE x,NODE y){
    return x.value==y.value?x.pos<y.pos:x.value<y.value;
}
void update(int x){
    for(;x<=n;x+=lowbit(x))
     tree[x]++;
}
int query(int x){
    int ans=0;
    for(;x;x-=lowbit(x))
     ans+=tree[x];
    return ans;
}
#undef int
int main()
#define int long long
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++){
        x[i].value=read();
        x[i].pos=i;
    }
    sort(x+1,x+1+n,cmp);
    int ans=0;
    for(int i=n;i>=1;i--){
        ans+=query(x[i].pos);
        update(x[i].pos);
    }
    printf("%lld\n",ans);
    return 0;
}

 

posted @ 2018-07-04 09:06  yjk  阅读(259)  评论(0编辑  收藏  举报