[트리] RUNNINGMEDIAN 변화하는 중간값
2021. 2. 7. 17:08ㆍ알고리즘/알고리즘 문제 [medium]
1. 균형잡힌 이진 검색트리를 이용한 풀이
트립 을 구현하여 수열이 추가될때마다 이진 검색트리를 유지 시키고,
k번째 수열을 찾는 kth함수를 구현하여 중간값을 찾는다.
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
|
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct NODE {
int priority;
int key, size;
NODE *right, *left;
NODE(const int& _key): key(_key), priority(rand()), size(1), right(NULL), left(NULL) {}
void calcSize() {
size = 1;
if(right) size+=right->size;
if(left) size+=left->size;
}
void setLeft(NODE* node) {
left = node;
calcSize();
}
void setRight(NODE* node) {
right = node;
calcSize();
}
};
typedef pair<NODE*, NODE*> CHILDPAIR;
CHILDPAIR split(NODE* root, int key) {
if(root == NULL) return CHILDPAIR(NULL, NULL);
if(root->key < key) {
CHILDPAIR rs = split(root->right, key);
root->setRight(rs.first);
return CHILDPAIR(root, rs.second);
}
CHILDPAIR ls = split(root->left, key);
root->setLeft(ls.second);
return CHILDPAIR(ls.first, root);
}
NODE* insert(NODE* root, NODE* node) {
if(root == NULL) return node;
if(root->priority < node->priority) {
CHILDPAIR child = split(root, node->key);
node->setLeft(child.first);
node->setRight(child.second);
return node;
}
if(root->key < node->key)
root->setRight(insert(root->right, node));
else
root->setLeft(insert(root->left, node));
return root;
}
NODE* merge(NODE* left, NODE* right) {
if(left == NULL) return right;
if(right == NULL) return left;
if(left->priority < right->priority) {
right->setLeft(merge(left, right->left));
return right;
}
left->setRight(merge(left->right, right));
return left;
}
NODE* erase(NODE* root, int key) {
if(root == NULL) return NULL;
if(key == root->key) {
NODE* ret = merge(root->left, root->right);
delete root;
return ret;
}
if(key < root->key) {
root->setLeft(erase(root->left, key));
}
else
root->setRight(erase(root->right, key));
return root;
}
NODE* kth(NODE* tree, int k) {
int leftSize = tree->left == NULL ? 0: tree->left->size;
if(leftSize + 1 == k) return tree;
if(leftSize < k) return kth(tree->right, k - leftSize - 1);
return kth(tree->left, k);
}
int testCase = 0;
int N;
int a, b;
const int MOD = 20090711;
int A(int i, const int* before = NULL)
{
if(i == 0) return 1983;
if(before==NULL)
return ((A(i-1)* (long long)a)%MOD + b )%MOD;
return (((*before) * (long long)a)%MOD + b )%MOD;
}
int median() {
int ret = 0;
int before = 1983;
NODE* tree = NULL;
for(int i = 0; i < N; i++) {
NODE* node = new NODE(A(i, &before));
tree = insert(tree, node);
ret = (ret+kth(tree, i/2 + 1)->key)%MOD;
before = node->key;
}
return ret;
}
//N median... even=> smaller
int main()
{
cin>>testCase;
while(testCase--)
{
cin>>N>>a>>b;
cout<<median()<<"\n";
}
}
|
cs |
2. 우선순위 큐를 이용한 풀이
수열을 절반으로 최대힙 | 최소힙으로 분리시킨다.
그러면 최대힙의 최대 원소가 최대값이 된다.
이러한 형태를 유지시키기위해서는 다음과 같은 불변식이 필요하다.
- 최대 힙의 크기는 최소 힙의 크기와 같거나, 하나 더 크다 (홀수인 경우)
- 최대 힙의 최대 원소는 최소 힙의 최소 원소보다 작거나같다.
책에서는 stl 인 priority_queue 를 사용하여 문제를 해결하였다.
priority_queue<int, vector<int>, less<int> > maxHeap;
priority_queue<int, vector<int>, greater<int> > minHeap;
maxHeap.size();
maxHeap.push(x);
maxHeap.pop();
maxHeap.top();
3. 실수들
트립구조체를 구현할 때 calcSize 에서 size = 1 이 아니라 size = 0으로 구현함.
erase를 구현할 때 delete를 안해줬다.
'알고리즘 > 알고리즘 문제 [medium]' 카테고리의 다른 글
[그래프] GALLERY 감시 카메라 설치 (0) | 2021.02.15 |
---|---|
[트리] EDITORWARS 에디터 전쟁 (0) | 2021.02.10 |
[문자열][시간 초과]HABIT 말장난 (0) | 2021.02.03 |
[비트 마스크] GRADUATION 졸업 학기 문제 (0) | 2021.01.30 |
[정수론] POTION 마법의 약 (0) | 2021.01.24 |