백준16975 수열과 쿼리21

문제 링크

  • http://icpc.me/16975

사용 알고리즘

  • Segment Tree
  • Lazy Propagation

시간복잡도

  • O(M log N)

풀이

Lazy Propagation을 구현해주면 됩니다.
약 1011까지 수가 커질 수 있으니 주의하시면 됩니다.

전체 코드

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
#include <bits/stdc++.h>
using namespace std;

template <typename T>
class segmentTree{
	private:
		vector<T> tree;
		vector<T> lazy;
		int n, h, size;

		T _init(int node, int start, int end){
			if(start == end) return tree[node] = arr[start];
			int mid = (start+end)>>1;
			return tree[node] = _init(node*2, start, mid) + _init(node*2+1, mid+1, end);
		}
		void update_lazy(int node, int start, int end, int left, int right){
			if(!lazy[node]) return;
			tree[node] += (end-start+1)*lazy[node];
			if(start^end){
				lazy[node*2] += lazy[node];
				lazy[node*2+1] += lazy[node];
			}
			lazy[node] = 0;
		}
		void update_range(int node, int start, int end, int left, int right, T diff){
			update_lazy(node, start, end, left, right);
			if(right<start || end<left) return;
			if(left<=start && end<=right){
				tree[node] += (end-start+1)*diff;
				if(start^end){
					lazy[node*2] += diff;
					lazy[node*2+1] += diff;
				}
				return;
			}
			int mid = (start+end)>>1;
			update_range(node*2, start, mid, left, right, diff);
			update_range(node*2+1, mid+1, end, left, right, diff);
			tree[node] = tree[node*2] + tree[node*2+1];
		}
		T q(int node, int start, int end, int left, int right){
			update_lazy(node, start, end, left, right);
			if(right<start || end<left) return 0;
			if(left<=start && end<=right) return tree[node];
			int mid = (start+end)>>1;
			return q(node*2, start, mid, left, right) + q(node*2+1, mid+1, end, left, right);
		}
	public:
		vector<T> arr;
		void init(){ _init(1, 0, n-1); }
		segmentTree(){
			this->n = 0;
			this->h = 0;
			this->size = 0;
		}
		segmentTree(int n){
			this->n = n;
			h = (int)ceil(log2(n))+1;
			size = 1<<h;
			arr = vector<T>(n);
			tree = vector<T>(size);
			lazy = vector<T>(size);
		}
		void update(int left, int right, T diff){ update_range(1, 0, n-1, left-1, right-1, diff); }
		T query(int left, int right){ return q(1, 0, n-1, left-1, right-1); }
};

int main(){
	ios_base::sync_with_stdio(0); cin.tie(0);
	int n, m, k;
	cin >> n;
	segmentTree<long long> st(n);
	for(int i=0; i<n; i++) cin >> st.arr[i];
	st.init();
	cin >> m;
	while(m--){
		int a, b, c;
		long long d;
		cin >> a >> b;
		if(a == 1){
			cin >> c;
			cin >> d;
			st.update(b, c, d);
		}else{
			cout << st.query(b, b) << "\n";
		}
	}
}