【洛谷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; }