题目链接:[蓝桥杯 2014 省 B] 小朋友排队 - 洛谷
标签:树状数组
思路:每个小朋友需要交换的次数=前面比他高的人数+后面比他矮的人数
用树状数组tr【i】记录身高小于i的人的个数
树状数组:树状数组与线段树模板_skyang.的博客-CSDN博客
代码:
#include<iostream>
#include<cstring>
using namespace std;
const int N = 100005;
const int M = 1000005;
int n;
int w[N];
int tr[N*10];
int cnt[N];
long long ans;
int lowbit(int x)
{
return x & -x;
}
void add(int u,int x)
{
for(int i=u;i<M;i+=lowbit(i))
{
tr[i]+=x;
}
}
int query(int x)
{
int res=0;
for(int i=x;i;i-=lowbit(i))
{
res+=tr[i];
}
return res;
}
int main()
{
cin>>n;
for(int i=1;i<=n;++i) cin>>w[i],w[i]++;
for(int i=1;i<=n;++i)
{
cnt[i]+=query(M-1)-query(w[i]);
add(w[i],1);
}
memset(tr,0,sizeof tr);
for(int i=n;i>=1;i--)
{
cnt[i]+=query(w[i]-1);
add(w[i],1);
}
for(int i=1;i<=n;++i)
{
ans+=(1+(long long)cnt[i])*cnt[i]/2;
}
cout<<ans<<endl;
return 0;
}