树状数组review
使用场景
有前缀思想,且需O(1e5)时间查询
例子
把数组1的地址映射到数组2上,对其进行前缀求和,即是前面出现了多少次,再求一次后缀,把结果累加
函数
插入
void inc(int x,int ad)
{
for(; x<= n; x += x&-x) f[x]+=ad;
}
求和
int calc(int x){
int Sum = 0;
for(; x ; x-= x&-x ) Sum += f[x];
return Sum;
例子的解
class Solution {
public:
int f[100001], c[100001];
long long v[100001];
inline void inc(int x) {
for (; x <= 100000; x += x & (-x))
f[x]++;
}
int calc(int x) {
int res = 0;
for (; x; x -= x & (-x))
res += f[x];
return res;
}
long long goodTriplets(vector<int>& a, vector<int>& b) {
long long ans = 0;
int n = a.size();
memset(f, 0, sizeof(f));
for (int i = 0; i < n; i++)
c[b[i]] = i;
for (int i = 0; i < n; i++) {
v[i] = calc(c[a[i]] + 1);
inc(c[a[i]] + 1);
}
memset(f, 0, sizeof(f));
for (int i = n - 1; i >= 0; i--) {
v[i] *= calc(100000) - calc(c[a[i]] + 1);
inc(c[a[i]] + 1);
}
for (int i = 0; i < n; i++)
ans += v[i];
return ans;
}
};
板子
using LL = long long;
struct BIT{
int n;
vector<LL> v;
BIT(int n) : n(n), v(n){
}
void add(int x, LL y) {
for (x += 1; x <= n; x += x & -x) v[x - 1] += y;
}
LL sum(int x) {
LL res = 0;
for (x += 1; x; x -= x & -x) res += v[x - 1];
return res;
}
};
class Solution {
public:
long long goodTriplets(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size();
vector<int> p(n), a(n);
for (int i = 0; i < n; i += 1) p[nums1[i]] = i;
for (int i = 0; i < n; i += 1) a[i] = p[nums2[i]];
vector<LL> bit(n);
BIT s(n), s2(n);
LL ans = 0;
for (int i = 0; i < n; i += 1) {
ans += s2.sum(a[i]);
s2.add(a[i], s.sum(a[i]));
s.add(a[i], 1);
}
return ans;
}
};
本文来自博客园,作者:InsiApple,转载请注明原文链接:https://www.cnblogs.com/InsiApple/p/15942404.html

浙公网安备 33010602011771号