/**********
Author Smile
学到了:
离散化:
1、用一个辅助的数组把你要离散的所有数据存下来。
2、排序,排序是为了后面的二分。
3、去重,因为我们要保证相同的元素离散化后数字相同。
4、索引,再用二分把离散化后的数字放回原数组。
本题的离散化是用于求在该速度之前的符和条件的点数
求出点数是为了用树状数组的思想减去前缀和
差值即为贡献
在树状数组中的数组,一个是记录点数,一个是记录前缀和
lowerbit 的本质最多才不超过30次忽略不计
时间复杂度 n * log n ;
https://vjudge.csgrandeur.cn/contest/482090#problem/F
**********/
#include <iostream>
#include <algorithm>
#define int long long
using namespace std;
const int N = 2e5 + 10;
int n;
int sum[N], cnt[N], vtemp[N];
struct node
{
int x, v;
} a[N];
int ans = 0;
bool comp(node a, node b)
{
return a.x < b.x;
}
int lowerbit(int x)
{
return x & (-x);
}
int query(int x, int w[])
{
int ans = 0;
while (x > 0)
{
ans += w[x];
x -= lowerbit(x);
}
return ans;
}
void add(int x, int w[], int value)
{
while (x <= N)
{
w[x] += value;
x += lowerbit(x);
}
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; ++i)
cin >> a[i].x;
for (int i = 1; i <= n; ++i)
{
cin >> a[i].v;
vtemp[i] = a[i].v;
}
sort(vtemp + 1, vtemp + 1 + n);
int len = unique(vtemp + 1, vtemp + 1 + n) - vtemp - 1;
sort(a + 1, a + 1 + n, comp);
for (int i = 1; i <= n; ++i)
{
int pos = lower_bound(vtemp + 1, vtemp + 1 + len, a[i].v) - vtemp;
ans += query(pos, cnt) * a[i].x - query(pos, sum);
add(pos, cnt, 1);
add(pos, sum, a[i].x);
}
cout << ans << endl;
return 0;
}
树状数组 + 离散化
于 2022-02-27 09:31:32 首次发布