---
tags: codebook
---
# 2d segment tree
**CSES - Forest Queries II**
```cpp=
constexpr int maxn=1e3+5;
int arr[(maxn+1)<<2][(maxn+1)<<2];
#define xm ((xl+xr)>>1)
#define ym ((yl+yr)>>1)
void _build(auto& v,int xi,int xl,int xr,int yi=1,int yl=0,int yr=maxn){
if(yr-yl==1){
if(xr-xl==1){
if(xl<int(v.size())&&yl<int(v.size()))
arr[xi][yi]=v[xl][yl];
}else
arr[xi][yi]=arr[xi<<1][yi]+arr[xi<<1|1][yi];
return;
}
_build(v,xi,xl,xr,yi<<1,yl,ym),_build(v,xi,xl,xr,yi<<1|1,ym,yr);
arr[xi][yi]=arr[xi][yi<<1]+arr[xi][yi<<1|1];
}
void build(auto& v,int xi=1,int xl=0,int xr=maxn){
if(xr-xl>1)
build(v,xi<<1,xl,xm),build(v,xi<<1|1,xm,xr);
_build(v,xi,xl,xr);
}
int _query(int yql,int yqr,int xi,int yi=1,int yl=0,int yr=maxn){
if(yqr<=yl||yr<=yql) return 0;
// debug(yl,yr);
if(yql<=yl&&yr<=yqr) return arr[xi][yi];
return _query(yql,yqr,xi,yi<<1,yl,ym)+_query(yql,yqr,xi,yi<<1|1,ym,yr);
}
int query(int xql,int xqr,int yql,int yqr,int xi=1,int xl=0,int xr=maxn){
if(xqr<=xl||xr<=xql) return 0;
// debug(xl,xr);
if(xql<=xl&&xr<=xqr) return _query(yql,yqr,xi);
return query(xql,xqr,yql,yqr,xi<<1,xl,xm)+query(xql,xqr,yql,yqr,xi<<1|1,xm,xr);
}
void _update(int yp,int xi,int xl,int xr,int yi=1,int yl=0,int yr=maxn){
if(yp<yl||yr<=yp) return;
if(yr-yl==1){
if(xr-xl==1)
arr[xi][yi]^=1;
else
arr[xi][yi]=arr[xi<<1][yi]+arr[xi<<1|1][yi];
return;
}
_update(yp,xi,xl,xr,yi<<1,yl,ym),_update(yp,xi,xl,xr,yi<<1|1,ym,yr);
arr[xi][yi]=arr[xi][yi<<1]+arr[xi][yi<<1|1];
}
void update(int xp,int yp,int xi=1,int xl=0,int xr=maxn){
if(xp<xl||xr<=xp) return;
if(xr-xl>1)
update(xp,yp,xi<<1,xl,xm),update(xp,yp,xi<<1|1,xm,xr);
_update(yp,xi,xl,xr);
}
void _print(auto& v,int xl,int xi,int yi=1,int yl=0,int yr=maxn){
if(yr-yl==1){if(yl<int(v.size())) debug(xl,yl,arr[xi][yi]);return;}
_print(v,xl,xi,yi<<1,yl,ym),_print(v,xl,xi,yi<<1|1,ym,yr);
}
void print(auto& v,int xi=1,int xl=0,int xr=maxn){
if(xr-xl>1)
print(v,xi<<1,xl,xm),print(v,xi<<1|1,xm,xr);
else
if(xl<int(v.size())) _print(v,xl,xi);
}
#undef xm
#undef ym
inline void solve() {
int n,m; cin>>n>>m;
V<V<int>> v(n,V<int>(n));
for(int i=0;i<n;i++){
string str;cin>>str;
for(int j=0;j<n;j++)
v[i][j]=(str[j]=='*');
}
build(v);
// cerr<<query(0,n,0,n)<<endl;
// cerr<<"poop"<<endl;
while(m--){
int op,x1,x2,y1,y2; cin>>op;
switch(op){
case 1:
cin>>x1>>y1,x1--,y1--;
update(x1,y1);
break;
case 2:
cin>>x1>>y1>>x2>>y2,x1--,y1--;
cout<<query(x1,x2,y1,y2)<<endl;
break;
}
}
}
```