1、知识点:逆序数、树状数组
2、思路:由于题目没有说明数据的范围,因此应该用数据离散化,用树状数组求和即可。
/*用途:
**说明:
**算法:
*/
//#define LOCAL
#include <cstdio>
#include <string.h>
#include <stack>
#include <algorithm>
using namespace std;
#define MAXN 100000+10
struct val_ind{ //定义值-下标结构
int val;
int ind;
};
int N;
val_ind vi[MAXN];
int tree_arr[MAXN]; //树状数组
int ref[MAXN]; //离散化数组
stack<int> s;
int cmp_val(const void* a, const void* b);
int low_bit(int a);
int get_sum(int ind);
void insert(int ind, int val);
int main()
{
#ifdef LOCAL
freopen("1009_Triple_Inversions.in", "r", stdin);
freopen("1010_Lehmer_Code.out", "w", stdout);
#endif
scanf("%d", &N);
for(int i=1; i<=N; i++){
scanf("%d", &(vi[i].val));
vi[i].ind = i;
}
qsort(vi+1, N, sizeof(val_ind), cmp_val);
for(int i=1; i<=N; i++) //离散化(逆序保存便于直接用树状数组求和)
ref[N+1-vi[i].ind] = i;
for(int i=1; i<=N; i++){
int ls = get_sum(ref[i]-1); //出现在arr[i]前面且比arr[i]小的数
s.push(ls); //由于是从原数组逆序依次求解,因此用栈保存
insert(ref[i], 1);
}
int s_top;
while(!s.empty()){ //打印结果
s_top = s.top();
s.pop();
if(!s.empty())
printf("%d ", s_top);
else
printf("%d", s_top);
}
return 0;
}
int cmp_val(const void* a, const void* b)
{
return (*(val_ind*)a).val - (*(val_ind*)b).val;
}
inline int low_bit(int a)
{
return a&(-a);
}
inline int get_sum(int ind)
{
int sum=0;
while(ind){
sum += tree_arr[ind];
ind -= low_bit(ind);
}
return sum;
}
inline void insert(int ind, int val)
{
while(ind <= N){ //因为离散化处理过,所以这里是N
tree_arr[ind] += val;
ind += low_bit(ind);
}
}