Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
segtree_2d.hpp
[詳解]
1#include"../../kyopro_library/template.hpp"
2
3template<typename Monoid>
5 using Type=Monoid::Type;
6
7 SegmentTree2D()=default;
8
9 /// @brief サイズ h * w の2次元セグメント木を構築する
10 SegmentTree2D(int h, int w) {
11 this->h=h,this->w=w;
12 dat=vector<vector<Type>>(this->h*2,vector<Type>(this->w*2,Monoid::id()));
13 }
14
15 /// @brief 位置 (x, y) の要素を v に更新する
16 /// @note O(log(h) log(w))
17 void set(int x, int y, Type v) {
18 x+=h,y+=w;
19 dat[x][y]=v;
20 for(int i=x>>1; i>0; i>>=1) dat[i][y]=Monoid::op(dat[i<<1][y],dat[i<<1|1][y]);
21 while(x>0) {
22 for(int j=y>>1; j>0; j>>=1) dat[x][j]=Monoid::op(dat[x][j<<1],dat[x][j<<1|1]);
23 x>>=1;
24 }
25 }
26
27 /// @brief 矩形領域 [l, r) × [u, d) のモノイド積を返す
28 /// @note O(log(h) log(w))
29 Type fold(int l, int r, int u, int d) {
30 Type ret=Monoid::id();
31 l+=h,r+=h,u+=w,d+=w;
32 while(l<r) {
33 if(l&1) ret=Monoid::op(ret,fold_sub(l++,u,d));
34 if(r&1) ret=Monoid::op(ret,fold_sub(--r,u,d));
35 l>>=1,r>>=1;
36 }
37 return ret;
38 }
39
40private:
41 int h,w;
42 vector<vector<Type>>dat;
43 Type fold_sub(int x, int u, int d) {
44 Type ret=Monoid::id();
45 while(u<d) {
46 if(u&1) ret=Monoid::op(ret,dat[x][u]),u++;
47 if(d&1) d--,ret=Monoid::op(ret,dat[x][d]);
48 u>>=1,d>>=1;
49 }
50 return ret;
51 }
52};
SegmentTree2D()=default
SegmentTree2D(int h, int w)
サイズ h * w の2次元セグメント木を構築する
Type fold(int l, int r, int u, int d)
矩形領域 [l, r) × [u, d) のモノイド積を返す
void set(int x, int y, Type v)
位置 (x, y) の要素を v に更新する