백준의 커피숍(1275) 문제이다.
[ 문제 바로가기 ]
[ 문제풀이 ]
구간에 대한 합을 구해야 하는 문제이다. 명령어 중간중간에는 값을 업데이트 해야 하는 부분도 있다.
'구간에 대한 연산'을 효율적으로 찾아낼 수 있는 세그먼트 트리를 통해서 해결할 수 있는 문제이다.
아직 세그먼트 트리에 대해서 잘 모른다면 아래의 글을 읽고 오도록 하자.
세그먼트 트리를 구현하는 내용만으로도 충분히 문제를 해결할 수 있기 때문에 별도의 설명 보다는 바로 소스코드로 대체하겠다.
[ 소스코드 ]
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 | #include<iostream> #include<vector> #include<cmath> #include<algorithm> #define endl "\n" #define MAX 100010 typedef long long ll; using namespace std; struct QUESTION { int x; int y; int a; int b; }; int N, Q; ll Array[MAX]; vector<ll> SegmentTree; vector<QUESTION> Cmd; void Input() { cin >> N >> Q; for (int i = 0; i < N; i++) cin >> Array[i]; for (int i = 0; i < Q; i++) { int x, y, a, b; cin >> x >> y >> a >> b; x--; y--; a--; Cmd.push_back({ x, y, a, b }); } } ll Make_SegmentTree(int Node, int Start, int End) { if (Start == End) return SegmentTree[Node] = (ll)(Array[Start]); int Mid = (Start + End) / 2; ll Left_Result = Make_SegmentTree(Node * 2, Start, Mid); ll Right_Result = Make_SegmentTree(Node * 2 + 1, Mid + 1, End); return SegmentTree[Node] = Left_Result + Right_Result; } ll Section_Sum(int Node, int Start, int End, int Left, int Right) { if (Right < Start || Left > End) return 0; if (Left <= Start && End <= Right) return SegmentTree[Node]; int Mid = (Start + End) / 2; ll Left_Result = Section_Sum(Node * 2, Start, Mid, Left, Right); ll Right_Result = Section_Sum(Node * 2 + 1, Mid + 1, End, Left, Right); return Left_Result + Right_Result; } void Update_Tree(int Node, int Start, int End, int Idx, ll Diff) { if (Idx < Start || Idx > End) return; SegmentTree[Node] = SegmentTree[Node] + Diff; if (Start != End) { int Mid = (Start + End) / 2; Update_Tree(Node * 2, Start, Mid, Idx, Diff); Update_Tree(Node * 2 + 1, Mid + 1, End, Idx, Diff); } } void Solution() { int Tree_Height = (int)ceil(log2(N)); int Tree_Size = (1 << (Tree_Height + 1)); SegmentTree.resize(Tree_Size); Make_SegmentTree(1, 0, N - 1); for (int i = 0; i < Cmd.size(); i++) { int x = Cmd[i].x; int y = Cmd[i].y; int a = Cmd[i].a; int b = Cmd[i].b; if (x > y) swap(x, y); cout << Section_Sum(1, 0, N - 1, x, y) << endl; ll Diff = b - Array[a]; Array[a] = b; Update_Tree(1, 0, N - 1, a, Diff); } } void Solve() { Input(); Solution(); } int main(void) { ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); //freopen("Input.txt", "r", stdin); Solve(); return 0; } | cs |
'[ BOJ Code ] > # BOJ -' 카테고리의 다른 글
[ 백준 1043 ] 거짓말 (C++) (0) | 2020.05.17 |
---|---|
[ 백준 2623 ] 음악 프로그램 (C++) (0) | 2020.05.15 |
[ 백준 11505 ] 구간 곱 구하기 (C++) (0) | 2020.05.14 |
[ 백준 1780 ] 종이의 개수 (C++) (0) | 2020.05.14 |
[ 백준 1074 ] Z (C++) (0) | 2020.05.13 |