一种离线时 O(q log n) 空间的二维树状数组
一种离线时 O(q log n) 空间的二维树状数组
若所有 \(q\) 个操作不预处理,每次都动态开点,时空复杂度则都是 \(O(q\log ^2n)\) 的(用哈希表存储)。
考虑将所有将来会执行修改操作的位置拎出来,对于第一维的每个位置,将第二维离散化,那么空间就是 \(O(q\log n)\) 的,操作时在第二维离散化后的数组上二分找到位置,时间复杂度还是 \(O(q\log ^2n)\),但时间常数也会显著减小。
实现如下:
const int N=1.5e5+5;
struct BIT {
vector<ll> s;
int n;
void init(int _n) {
n=_n;
s.assign(n+1,0);
}
void update(int x,ll y) {
while(x<=n) s[x]+=y,x+=lowbit(x);
}
ll query(int x) {
ll res=0;
while(x) res+=s[x],x-=lowbit(x);
return res;
}
};
int n;
struct BIT2D {
vi ys[N];
BIT s[N];
void add(int x,int y) { // 预处理,加入可能的位置
while(x<=n) ys[x].pb(y),x+=lowbit(x);
}
void build() { // 离散化
fo(i,1,n) {
sort(ys[i].begin(),ys[i].end());
ys[i].resize(unique(ys[i].begin(),ys[i].end())-ys[i].begin());
s[i].init(Size(ys[i]));
}
}
int getid(int x,int y) { // 找到对应位置
//注意要使用 upper_bound-1 应对查询位置修改时没出现的情况
return upper_bound(ys[x].begin(),ys[x].end(),y)-ys[x].begin();
}
void update(int x,int y,ll z) {
while(x<=n) s[x].update(getid(x,y),z),x+=lowbit(x);
}
ll query(int x,int y) {
ll res=0;
while(x) res+=s[x].query(getid(x,y)),x-=lowbit(x);
return res;
}
void clear() {
fo(i,1,n) s[i].init(s[i].n);
}
};

浙公网安备 33010602011771号