一种离线时 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号