蓝桥集训之小朋友排队(树状数组)
-
核心思想:树状数组
- 小朋友交换次数 = 左边比他高+右边比他低
-
#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int N = 1000010; typedef long long LL; int tr[N],a[N],sum[N]; int n; int lowbit(int x) { return x & -x; } void add(int x,int c) { for(int i=x;i<N;i+=lowbit(i)) tr[i] +=c; } 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=0;i<n;i++) cin>>a[i] , a[i]++; //身高可能为0 先++再操作 for(int i=0;i<n;i++) //左边比他高 { sum[i] = query(N-1) - query(a[i]); add(a[i],1); } memset(tr, 0, sizeof tr); for (int i = n - 1; i >= 0; i -- ) //右边比他低 { sum[i] += query(a[i] - 1); add(a[i], 1); } LL res = 0; for (int i = 0; i < n; i ++ ) res += (LL)sum[i] * (sum[i] + 1) / 2; cout << res << endl; return 0; }