1716: LR数组(New Online Judge)

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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值