楼兰图腾【树状数组】
CH4201
、ACwing241
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 2e5;
int a[N + 5],tree[N + 5]; //原始序列、树状数组
int n,ans1,ans2; //n、尖刀、铁锹
int top[N + 5],but[N + 5]; //分别表示第i个点前面比它大的、比它小的数的个数
void update(int x){ //更新树状数组
for(;x <= n;x += x & -x)
tree[x] += 1;
}
int get_sum(int x){ //求前缀和
int ans = 0;
for(;x;x -= x & -x)
ans += tree[x];
return ans;
}
signed main(){
cin>>n;
for(int i = 1;i <= n;++i)
cin>>a[i];
for(int i = 1;i <= n;++i){
update(a[i]);
but[i] = get_sum(a[i]) - 1;
top[i] = i - get_sum(a[i]);
}
memset(tree,0,sizeof(tree));
for(int i = n;i > 0;--i){
update(a[i]);
ans1 += top[i] * (get_sum(n) - get_sum(a[i])); //这个位置前面比它大的数的个数和后面的个数相乘累加就是尖刀
ans2 += but[i] * (get_sum(a[i]) - 1); //这个位置前面比它小的数的个数和后面的个数相乘累加就是铁锹
}
cout<<ans1<<" "<<ans2;
return 0;
}