1716: LR数组(New Online Judge)
题目描述
现在给你一个长度为n的数组。对于这个数组,我们分别定义L数组和R数组。
L数组:L[i]表示在a[1]-a[i]中,数值小于等于a[i]的数量。
R数组:R[i]表示在a[i]-a[n]中,数值大于等于a[i]的数量。
请求出L[1]*R[1]+L[2]*R[2]+…+L[n]*R[n]
输入
输入第一个行为正整数n,不超过 1 0 5 10^5 105。
第二行包含n个正整数,表示数组a。数字不超过 1 0 9 10^9 109(数据范围过大,需要离散化)
输出
输出一个正整数表示答案。
样例输入
5
1 5 3 6 2
样例输出
19
题解1(C++版本)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
#define lowbit(x) ((x) & (-x))
int n, tree[N], A[N], L[N], R[N]; //数组tree树状数组 数组A离散后的原始数组
struct node{
int val; //序列元素的值
int pos; //原始序号
}t[N]; //存入输入数据
bool cmp(const node&a, const node& b){
return a.val < b.val;
}
// 单点修改
void update(int x, int v){ //修改元素a[x], a[x] += v
for(int i = x; i <= n; i += lowbit(i)){
tree[i] += v;
}
}
// 区间查询
int getSum(int x){ //返回值是前缀和: sum = a[1]+a[2]+...+a[x]
int sum = 0;
for(int i = x; i > 0; i -= lowbit(i)){
sum += tree[i];
}
return sum;
}
int main(){
scanf("%d", &n);
for(int i = 1; i <= n; i++) {
scanf("%d", &t[i].val);
t[i].pos = i;
}
sort(t + 1, t + n + 1, cmp);
for(int i = 1; i <= n; i++){ // 数据范围离散化
if(i == 1 || t[i].val != t[i - 1].val){
A[t[i].pos] = i;
}else { //与前一个元素的值相等
A[t[i].pos] = A[t[i - 1].pos];
}
}
for(int i = 1; i <= n; i++){
update(A[i], 1); // A[i]的出现次数+1
L[i] = getSum(A[i]); // 查询当前<=A[i]的数的个数
}
memset(tree, 0, sizeof tree); //清空树状数组
for(int i = n; i > 0; i--){
update(A[i], 1);
R[i] = getSum(n) - getSum(A[i] - 1); //查询当前>=A[i]的数的个数
}
long long ans = 0;
for(int i = 1; i <= n; i++){
ans += L[i]*R[i];
}
printf("%lld\n", ans);
return 0;
}