Submission #61979


ソースコード

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
#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)の範囲外なら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)の範囲外なら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(){
auto fx=[](long long x1,long long x2) -> long long {return (x1+x2);};
long long ex=0;
int n,q;
cin>>n>>q;
SegTree<long long> seg(n,fx,ex);
for(int i=0;i<q;i++){
long long s,a,b;
cin>>s>>a>>b;
a--;
if(s==0){
seg.update(a,seg[a]+b);
}
else{
b--;
cout<<seg.query(a,b+1)<<'\n';
}
}
return(0);
}

ステータス

項目 データ
問題 0649 - 区間和(セグ木、BIT練習)
ユーザー名 ei1918
投稿日時 2020-08-12 13:23:55
言語 C++14
状態 Accepted
得点 5
ソースコード長 3599 Byte
最大実行時間 1484 ms
最大メモリ使用量 119912 KB

セット

セット 得点 Cases
1 ALL 5 / 5 *

テストケース

ファイル名 状態 実行時間 メモリ使用量 #
input100-1 AC 103 ms 988 KB
1
input100-2 AC 235 ms 1848 KB
1
input100-3 AC 495 ms 4120 KB
1
input100-4 AC 942 ms 8824 KB
1
input100-5 AC 1422 ms 15960 KB
1
input1000-1 AC 475 ms 18100 KB
1
input1000-2 AC 1066 ms 23160 KB
1
input1000-3 AC 539 ms 25408 KB
1
input1000-4 AC 1357 ms 31748 KB
1
input1000-5 AC 417 ms 33480 KB
1
input10000-1 AC 1253 ms 39692 KB
1
input10000-2 AC 1435 ms 45872 KB
1
input10000-3 AC 1073 ms 50896 KB
1
input10000-4 AC 1234 ms 56440 KB
1
input10000-5 AC 633 ms 59292 KB
1
input100000-1 AC 1484 ms 68544 KB
1
input100000-2 AC 240 ms 69484 KB
1
input100000-3 AC 261 ms 70428 KB
1
input100000-4 AC 783 ms 73796 KB
1
input100000-5 AC 1294 ms 79348 KB
1
input1000000-1 AC 173 ms 108192 KB
1
input1000000-2 AC 579 ms 110316 KB
1
input1000000-3 AC 662 ms 112832 KB
1
input1000000-4 AC 1263 ms 117780 KB
1
input1000000-5 AC 562 ms 119912 KB
1
input1001000-1 AC 21 ms 88632 KB
1
input1001000-2 AC 26 ms 88472 KB
1
input1001000-3 AC 23 ms 88444 KB
1
input1001000-4 AC 20 ms 88412 KB
1
input1001000-5 AC 22 ms 88504 KB
1