| ||||||||||
| Online Judge | Problem Set | Authors | Online Contests | User | ||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Web Board Home Page F.A.Qs Statistical Charts | Current Contest Past Contests Scheduled Contests Award Contest | |||||||||
Re:Did you initialize array answer[...]?In Reply To:Did you initialize array answer[...]? Posted by:C6H6 at 2006-03-14 22:47:54 I think init of answer array is not needed because it overlaped by another set of questions.
and...
this is my RB Tree.
but this is very long... that's reason why i didn't post it
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <string>
#include <ctime>
#include <algorithm>
#include <set>
using namespace std;
class Node {
public:
Node* left;
Node* right;
int red; // 0 black 1 red
int key;
int treesize;
Node() {
left = NULL, right = NULL;
red = 0;
key = 0;
treesize = 1;
}
Node(int key) {
left = NULL, right = NULL;
red = 0;
this->key = key;
treesize = 1;
}
};
class RedBlack {
public:
int treesize;
Node* base;
RedBlack() {
base = new Node();
treesize = 0;
}
~RedBlack() {
queue<Node*> bfs;
bfs.push(base);
while(!bfs.empty()) {
Node* now = bfs.front();
bfs.pop();
if (now) {
bfs.push(now->left);
bfs.push(now->right);
delete now;
now = NULL;
}
}
}
int size() {
return treesize;
}
//찾으면 Node* 리턴. 못찾으면 Null 리턴
//base의 left가 root
Node* find(int key)
{
Node* s = base->left;
while(s != NULL && s->key != key) {
if (s->key > key) {
s = s->left;
}
else {
s = s->right;
}
}
return s;
}
int rank(int k)
{
if (k < 0 || k > base->left->treesize) return -1;
Node* s = base->left;
int nodenum = 1;
while(1)
{
if (s->left) nodenum += s->left->treesize;
if (nodenum == k) return s->key;
if (k < nodenum) {
nodenum -= s->left->treesize;
s = s->left;
}
else {
nodenum++;
s = s->right;
}
}
//should not reached
printf("should not reached!!!!\n");
(*(int *)0) = 0;
return -1;
}
//pivot의 위치는 변하지 않고, gchild가 회전된 서브트리의 root가 된다.
//회전된 서브트리의 root의 Pointer가 리턴
Node* rotate(Node* pivot, int key)
{
Node* child, *gchild;
if (key < pivot->key || pivot == base) child = pivot -> left;
else child = pivot -> right;
int save = child->treesize;
if (key < child->key) { //L 회전
gchild = child->left;
child->treesize -= gchild->treesize;
if (gchild->right) child->treesize += gchild->right->treesize;
child->left = gchild->right;
gchild->right = child;
}
else { //R 회전
gchild = child->right;
child->treesize -= gchild->treesize;
if (gchild->left) child->treesize += gchild->left->treesize;
child->right = gchild->left;
gchild->left = child;
}
gchild->treesize = save;
if (key < pivot->key || pivot == base) pivot->left = gchild;
else pivot->right = gchild;
return gchild;
}
Node* insert(int key)
{
Node* t, *parent, *gparent, *ggparent;
ggparent = gparent = parent = base;
t = base->left;
while(t != NULL) {
if (key == t->key) return NULL; //이미 같은 키가 존재
if (t->left != NULL && t-> right != NULL && t->left->red && t->right->red) { //색상변환
t->red = 1;
t->left->red = 0, t->right->red = 0;
if (parent->red) { //부모가 빨강이면 회전 필요
gparent->red = 1;
if ((key < gparent->key) != (key < parent->key)) //LR이나 RL의 첫 회전
parent = rotate(gparent, key);
t = rotate(ggparent, key);
t->red = 0;
}
base->left->red = 0; //root는 항상 검정
}
ggparent = gparent;
gparent = parent;
parent = t;
if (key < t->key) t = t->left;
else t = t->right;
}
t = new Node(key);
if (key < parent->key || parent == base) parent->left = t;
else parent->right = t;
t->red = 1; //새로 삽입된 노드는 빨강
//root에서 t의 parent까지 treesize에 1을 더한다
Node* s = base->left;
while(s != NULL && s->key != key) {
s->treesize ++;
if (s->key > key) {
s = s->left;
}
else {
s = s->right;
}
}
if (parent->red) {
gparent->red = 1;
if ((key < gparent->key) != (key < parent->key)) //LR이나 RL의 첫 회전
parent = rotate(gparent, key);
t = rotate(ggparent, key);
t->red = 0;
}
base->left->red = 0;
treesize++;
return t;
}
//삭제 노드와 가장 가까운 빨강 씨앗을 찾아서 빨강 씨앗의 부모의 포인터 리턴
//이 빨강 씨앗을 아래로 보내면서 삭제한다
Node* find_seed(int key)
{
Node* del, *seed_parent, *parent;
seed_parent = NULL;
parent = base;
del = base->left;
while(del != NULL) {
if (key < del->key) {
//빨강노드나 오른쪽 자식이 빨간 노드 찾기
if (del->red || (del->right && del->right->red)) seed_parent = parent;
parent = del;
del = del->left;
}
else {
//빨강노드나 왼쪽 자식이 빨간 노드 찾기
if (del->red || (del->left && del->left->red)) seed_parent = parent;
parent = del;
del = del->right;
}
}
return seed_parent;
}
//원하는 key값의 노드를 red 노드로 만든다.
//red노드의 leaf노드만 삭제 가능 : 3노드나 4노드이기 때문
void make_leaf_red(int key)
{
Node* seed_parent, *seed, *seed_child;
seed_parent = find_seed(key);
if (seed_parent == NULL) { //빨강 씨앗이 없으면
seed_parent = base;
seed = seed_parent->left;
seed->red = 1; //루트를 빨강으로 잠시 칠한다
}
else {
//시드 설정
if (key < seed_parent->key || seed_parent == base) seed = seed_parent->left;
else seed = seed_parent->right;
}
//씨앗이 빨강이 아니면 그 자식을 끌어 올린다.
if (!seed->red) {
if (key < seed->key) seed_child = seed->right;
else seed_child = seed->left;
seed->red = 1;
seed_child->red = 0;
seed_parent = rotate(seed_parent, seed_child->key);
}
//외부노드가 아닐 동안
while(seed->left && seed->right) {
/*
printf("now seed's key value is [%c]\n", seed->key);
printf("now seed's left child's key value is [%c]\n", seed->left->key);
printf("now seed's right child's key value is [%c]\n", seed->right->key);
print(base, 0);
*/
seed->red = 0;
seed->right->red = seed->left->red = 1;
if (key < seed->key) {
//if ((seed->right->left || seed->right->right) &&
// (seed->right->left->red || seed->right->right->red)) {
if ((seed->right->left && seed->right->left->red) ||
(seed->right->right && seed->right->right->red)) {
if (seed->right->left && seed->right->left->red) { //RL회전
seed->right->red = 0;
rotate(seed, seed->right->left->key);
}
else { //RR회전
seed->right->right->red = 0;
}
rotate(seed_parent, seed->right->key);
}
seed_parent = seed;
seed = seed->left;
}
else {
//if ((seed->left->left || seed->left->right) &&
// (seed->left->left->red || seed->left->right->red)) {
if ((seed->left->left && seed->left->left->red) ||
(seed->left->right && seed->left->right->red)) {
if (seed->left->right && seed->left->right->red) { //LR회전
seed->left->red = 0;
rotate(seed, seed->left->right->key);
}
else {
seed->left->left->red = 0; //LL회전
}
rotate(seed_parent, seed->left->key);
}
seed_parent = seed;
seed = seed->right;
}
}
}
//이 함수를 사용할 떄 반드시 원소가 레드블랙 트리 안에 있는지 체크해 보고 사용할 것!
//없으면 서브트리의 크기가 뻑남
//검색하고 시작하도록 해도 되지만 그냥 안했음
//삭제가 실패하면 NULL 리턴
Node* erase(int key)
{
Node* parent, *del, *center, *pcenter, *son;
parent = base;
del = base->left;
//원소 찾기 : parent를 알아야 하기 때문에 search함수 안씀
while(del != NULL && key != del->key) {
del->treesize --;
parent = del;
if (key < del->key) del = del->left;
else del = del->right;
}
if (del == NULL) return NULL;
del->treesize --;
if (del->right && del->left) { //내부 노드이면
pcenter = del; //삭제할 노드를 대체할 노드를 찾음
center = del->right;
while(center->left != NULL) {
center->treesize--;
pcenter = center;
center = center->left; //center는 대체할 키임
}
del->key = center->key; //삭제할 키를 대체할 키로 바꿈
del = center; //이제 center를 삭제하도록 조정
parent = pcenter;
key = del->key;
}
if (del->left || del->right) { //자식이 하나면 반드시 빨강
if (del->left) son = del->left;
else son = del->right;
son->red = 0;
}
else if (del->left == NULL && del->right == NULL) {
//자식이 없으면 빨강이면 삭제 검정이면 변환 후 삭제
if (!del->red) make_leaf_red(del->key);
son = NULL;
}
base->left->red = 0;
if (key < parent->key || parent == base) parent->left = son;
else parent->right = son;
delete del;
treesize--;
return parent;
}
void printrecur(Node* node, int depth)
{
if (node == NULL) return;
//for (int i = 0; i < depth; i++) printf("\t");
printf("%d ", node->key);
/*
if (node->red) printf("%c[R](size = %d)\n", (char)(node->key), node->treesize);
else printf("%c[B](size = %d)\n", (char)(node->key), node->treesize);
*/
printrecur(node->left, depth + 1);
printrecur(node->right, depth + 1);
}
void print()
{
printf("[");
printrecur(base->left, 0);
printf("]\n");
}
};
int n, m;
int a[100000];
struct query {
int num;
int l, r, rank;
};
bool operator < (const query& a, const query& b)
{
if (a.l == b.l) {
return (a.r < b.r);
}
return (a.l < b.l);
}
query q[50000];
int answer[50000];
int main()
{
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
for (int i = 0; i < m; i++) {
scanf("%d%d%d", &q[i].l, &q[i].r, &q[i].rank);
if (q[i].l > q[i].r) {
int temp = q[i].l; q[i].l = q[i].r; q[i].r = temp;
}
q[i].l--, q[i].r--;
q[i].num = i;
//printf("%d %d %d\n", q[i].l, q[i].r, q[i].rank);
}
sort(q, q + m);
RedBlack rb;
for (int i = q[0].l; i <= q[0].r; i++) {
rb.insert(a[i]);
}
answer[q[0].num] = rb.rank(q[0].rank);
for (int i = 1; i < m; i++) {
if (q[i - 1].r >= q[i].r) {
(* (int *)0) = 0;
}
if (q[i - 1].r < q[i].l) {
for (int j = q[i - 1].l; j <= q[i - 1].r; j++) rb.erase(a[j]);
for (int j = q[i].l; j <= q[i].r; j++) rb.insert(a[j]);
}
else {
for (int j = q[i - 1].l; j < q[i].l; j++) rb.erase(a[j]);
for (int j = q[i - 1].r + 1; j <= q[i].r; j++) rb.insert(a[j]);
}
answer[q[i].num] = rb.rank(q[i].rank);
}
for (int i = 0; i < m; i++) {
printf("%d\n", answer[i]);
}
return 0;
}
Followed by:
Post your reply here: |
All Rights Reserved 2003-2013 Ying Fuchen,Xu Pengcheng,Xie Di
Any problem, Please Contact Administrator