Submission #62121
ソースコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | #include<bits/stdc++.h> using namespace std; /*SegTree<x>(n,fx,ex): モノイド(集合X,二項演算fx,単位元ex)についてサイズnで構築 set(int i,X x),build(): i番目の要素をxにセット。まとめてセグ木を構築する0(n) update(i,x): i番目の要素をxに更新。O(log(n)) query(a,b): [a,b) 全てにfxを作用させた値を取得。O(log(n)) operator[k] := k番目の要素を返す。 find_rightest : [a,b) で x以下の要素を持つ最右位置はどこか find_leftest : [a,b) で x以下の要素を持つ最左位置はどこか */ template < typename X> struct SegTree{ using FX=function<X(X,X)>; //X●X -> X となる関数の型 int n; FX fx; const X ex; vector<X> dat; SegTree( int size,FX fx_,X ex_) : n(),fx(fx_),ex(ex_),dat(size*4,ex_){ int x=1; while (size>x){ x*=2; } n=x; return ; } void set( int i,X x){ dat[i+n-1]=x;} void build(){ for ( int k=n-2;k>=0;k--) dat[k]=fx(dat[2*k+1],dat[2*k+2]); return ; } void update( int i,X x){ i+=n-1; dat[i]=x; while (i>0){ i=(i-1)/2; dat[i]=fx(dat[i*2+1],dat[i*2+2]); } return ; } X query( int a, int b){ return (query_sub(a,b,0,0,n));} X query_sub( int a, int b, int k, int l, int r){ if (r<=a || b<=l){ return ex; } else if (a<=l && r<=b){ return dat[k]; } else { X vl=query_sub(a,b,k*2+1,l,(l+r)/2); X vr=query_sub(a,b,k*2+2,(l+r)/2,r); return fx(vl,vr); } } X operator[]( const int &k) const { return dat[k+n-1]; } X find_rightest( int a, int b, X x) { return find_rightest_sub(a, b, x, 0, 0, n); } X find_leftest( int a, int b, X x) { return find_leftest_sub(a, b, x, 0, 0, n); } X find_rightest_sub( int a, int b, X x, int k, int l, int r) { if (dat[k] > x || r <= a || b <= l) { // 自分の値がxより大きい or [a,b)が[l,r)の範囲外 return a - 1; } else if (k >= n - 1) { // 自分が葉ならその位置をreturn return (k - (n - 1)); } else { int vr = find_rightest_sub(a, b, x, 2 * k + 2, (l + r) / 2, r); if (vr != a - 1) { // 右の部分木を見て a-1 以外ならreturn return vr; } else { // 左の部分木を見て値をreturn return find_rightest_sub(a, b, x, 2 * k + 1, l, (l + r) / 2); } } } X find_leftest_sub( int a, int b, X x, int k, int l, int r) { if (dat[k] > x || r <= a || b <= l) { // 自分の値がxより大きい or [a,b)が[l,r)の範囲外 return b; } else if (k >= n - 1) { // 自分が葉ならその位置をreturn return (k - (n - 1)); } else { int vl = find_leftest_sub(a, b, x, 2 * k + 1, l, (l + r) / 2); if (vl != b) { // 左の部分木を見て b 以外ならreturn return vl; } else { // 右の部分木を見て値をreturn return find_leftest_sub(a, b, x, 2 * k + 2, (l + r) / 2, r); } } } }; int main(){ int n,m; cin>>n>>m; auto fx=[]( int x1, int x2) -> int { return min(x1,x2);}; int ex=numeric_limits< int >::max(); SegTree< int > minseg(n,fx,ex); auto fx2=[]( int x1, int x2) -> int { return max(x1,x2);}; int ex2=-ex; SegTree< int > maxseg(n,fx2,ex2); auto fx3=[]( int x1, int x2) -> int { return (x1+x2);}; int ex3=0; SegTree< int > sumseg(n,fx3,ex3); string s; int a,b; for ( int i=0;i<n;i++){ minseg.update(i,0); maxseg.update(i,0); sumseg.update(i,0); } for ( int i=0;i<m;i++){ cin>>s>>a>>b; if (s== "update" ){ minseg.update(a,b); maxseg.update(a,b); sumseg.update(a,b); } else if (s== "add" ){ minseg.update(a,minseg[a]+b); maxseg.update(a,maxseg[a]+b); sumseg.update(a,sumseg[a]+b); } else if (s== "getMin" ){ cout<<minseg.query(a,b)<< '\n' ; } else if (s== "getMax" ){ cout<<maxseg.query(a,b)<< '\n' ; } else { cout<<sumseg.query(a,b)<< '\n' ; } } return (0); } |
ステータス
項目 | データ |
---|---|
問題 | 1072 - セグメントツリー技術基礎 |
ユーザー名 | immunity |
投稿日時 | 2020-08-13 15:54:40 |
言語 | C++17 |
状態 | Accepted |
得点 | 1 |
ソースコード長 | 4260 Byte |
最大実行時間 | 210 ms |
最大メモリ使用量 | 10756 KB |
セット
セット | 得点 | Cases | |
---|---|---|---|
1 | ALL | 1 / 1 | * |
テストケース
ファイル名 | 状態 | 実行時間 | メモリ使用量 | # |
---|---|---|---|---|
in01 | AC | 26 ms | 604 KB |
1
|
in02 | AC | 133 ms | 952 KB |
1
|
in03 | AC | 120 ms | 5416 KB |
1
|
in04 | AC | 162 ms | 5220 KB |
1
|
in05 | AC | 62 ms | 5764 KB |
1
|
in06 | AC | 98 ms | 3596 KB |
1
|
in07 | AC | 104 ms | 3320 KB |
1
|
in08 | AC | 185 ms | 3072 KB |
1
|
in09 | AC | 164 ms | 5320 KB |
1
|
in10 | AC | 191 ms | 3836 KB |
1
|
in11 | AC | 50 ms | 3364 KB |
1
|
in12 | AC | 76 ms | 2436 KB |
1
|
in13 | AC | 157 ms | 7120 KB |
1
|
in14 | AC | 210 ms | 4044 KB |
1
|
in15 | AC | 132 ms | 6880 KB |
1
|
in16 | AC | 157 ms | 3772 KB |
1
|
in17 | AC | 153 ms | 6776 KB |
1
|
in18 | AC | 85 ms | 8020 KB |
1
|
in19 | AC | 154 ms | 7336 KB |
1
|
in20 | AC | 92 ms | 7408 KB |
1
|
in21 | AC | 108 ms | 6560 KB |
1
|
in22 | AC | 184 ms | 6948 KB |
1
|
in23 | AC | 145 ms | 8556 KB |
1
|
in24 | AC | 160 ms | 7636 KB |
1
|
in25 | AC | 156 ms | 5928 KB |
1
|
in26 | AC | 184 ms | 9956 KB |
1
|
in27 | AC | 172 ms | 9968 KB |
1
|
in28 | AC | 206 ms | 7720 KB |
1
|
in29 | AC | 73 ms | 9656 KB |
1
|
in30 | AC | 178 ms | 10756 KB |
1
|
in31 | AC | 99 ms | 8420 KB |
1
|
in32 | AC | 164 ms | 8432 KB |
1
|