2018-03-16 失败的刷题 AVL树

1067 Sort with Swap(0,*) 麻烦

题目很简单,给一个 [0, N)乱序的序列,n <= 10 ^ 5,只能用 0 和其它元素交换,问要交换多少次才能恢复升序。

想了想没有想到计算的办法,那就模拟吧。刚开始只存了这个序列,需要找元素的时候就得顺序查找,果然超时了。

改,又用了一个反向索引,记录每一个元素目前的位置。结果还有 case 超时。

后来终于不超时了。我放弃了之前“寻找还有没有不在其位的元素”的时候顺序查找的办法,而是用一个值记录还有多少个元素乱序。这里又折腾了半天,因为没想通,一般交换一次是有一个元素归位,但是当交换一个环,0恰好也归位时会多有一个元素归位;一个环结束后还得把 0 拿出来以启动下一次交换,这个操作会把本身在位置的 0 拉出来,乱序元素会增加 1。当乱序元素数为 0,就可以结束循环了。

不过把 0 拉出来跟任意一个乱序元素交换的时候,又涉及到顺序查找哪个元素是乱的。这里又用了一个数 wrong0 记录第一个乱序的元素,它每次都继续往后走,就不用从头循环了。

总之,当我去除了所有存在的顺序查找/遍历操作,就不超时了:-) 真是有毒的题。

丑唧唧的代码:

# include 
# include 

int seq[100100];
int N;
int ans = 0;
int idx[100100]; //反向查找
int nWrong = 0;
int wrong0 = 1;

void swap(int n) { //0与n交换
    //printf("swap 0 and %3d: ", n);
    int idx0 = idx[0];
    seq[idx[n]] = 0; idx[0] = idx[n];
    seq[idx0] = n; idx[n] = idx0;
    ans++;
}

int main() {
    scanf("%d", &N);
    for (int i = 0; i < N; i++) {
        scanf("%d", seq + i);
        idx[seq[i]] = i;
        if (seq[i] != i) {
            nWrong++;
        }
    }

    int temp;
    while (nWrong > 0) {
        if (idx[0] == 0) {
            //找一个交换
            for (; wrong0 < N; wrong0++) {
                if (idx[wrong0] != wrong0) {
                    swap(seq[wrong0]);
                    nWrong ++;
                    break;
                }
            }
        }
        else {
            swap(idx[0]);
            nWrong--;
            if (idx[0] == 0) nWrong--;
        }
        /*for (int i = 0; i < N; i++) {
            printf("%d ", seq[i]);
        }printf("\n");
        for (int i = 0; i < N; i++) {
            printf("%d ", idx[i]);
        }printf("\n");
        printf("nWrong = %d\n", nWrong);*/
    }

    printf("%d", ans);

    return 0;
}

1066 Root of AVL Tree AVL树!

简单粗暴考你 AVL 树:给一个插入的序列,求最后树根是几。我佛佛佛。。。算了,认真写吧。在两眼一抹黑,也找不到之前写过的 AVL 树的情况下,凭着我奇葩的想象力,楞是从题目配图里找到了 AVL 树的规律。经过长时间的 debug (主要是处理不好 NULL 和 root 节点,到处报错)之后竟然通过了。。。通过了。。。

# include 

#define max(a,b) ((a)>(b)? (a):(b))

struct node {
    int data;
    node *p, *lc, *rc;
};

node *root = NULL;
int N;

int hgt(node* pos) { //节点的高度,空树的高度为-1,单个节点的高度为0,有一个孩子的节点高度为1
    if (pos == NULL) return -1;
    return max(hgt(pos->lc), hgt(pos->rc)) + 1;
}

int balFac(node *pos) { //左孩子高度-右孩子高度
    int lh, rh;
    if (pos->lc == NULL) lh = -1; else lh = hgt(pos->lc);
    if (pos->rc == NULL) rh = -1; else rh = hgt(pos->rc);
    return lh - rh;
}

void insertAsRoot(int n) { //插入 root
    root = new node;
    root->data = n;
    root->lc = NULL;
    root->rc = NULL;
    root->p = NULL;
}

node *insertAsLc(node *pos, int n) { //插入到pos的左孩子
    node *newnode = new node;
    newnode->data = n;
    newnode->lc = NULL;
    newnode->rc = NULL;
    newnode->p = pos;
    pos->lc = newnode;
    return newnode;
}

node *insertAsRc(node *pos, int n) { //插入到pos的右孩子
    node *newnode = new node;
    newnode->data = n;
    newnode->lc = NULL;
    newnode->rc = NULL;
    newnode->p = pos;
    pos->rc = newnode;
    return newnode;
}

void leftRotate(node *pos) {
    node *b = pos->rc, *c = pos->rc->rc, *d = pos->rc->lc, *e = pos->lc;
    if (pos->p) {
        if (pos->p->lc == pos) { //是左孩子
            pos->p->lc = b;
        }
        else if (pos->p->rc == pos) { //是右孩子
            pos->p->rc = b;
        }
    }
    else {
        root = b;
    }
    b->p = pos->p;
    pos->rc = d; if (d) d->p = pos;
    b->lc = pos; pos->p = b;
}

void rightRotate(node *pos) {
    node *b = pos->lc, *c = pos->lc->lc, *d = pos->lc->rc, *e = pos->rc;
    if (pos->p) {
        if (pos->p->lc == pos) { //是左孩子
            pos->p->lc = b;
        }
        else if (pos->p->rc == pos) { //是右孩子
            pos->p->rc = b;
        }
    }
    else { //转的是root
        root = b;
    }
    b->p = pos->p;
    pos->lc = d; if(d) d->p = pos;
    pos->p = b; b->rc = pos;
}

void insert(int n) {
    if (root == NULL) { //空的
        insertAsRoot(n);
    }
    else { //树非空
        node *x = root, *prev = NULL;
        while (x) {
            if (n < x->data) {
                prev = x; x = x->lc;
            }
            else {
                prev = x; x = x->rc;
            }
        }
        if (n < prev->data) x = insertAsLc(prev, n); else x = insertAsRc(prev, n); //插入节点
        x = x->p->p; //爷爷可能开始不平衡
        while (x) { //找最先失衡的祖先
            if (balFac(x) >= 2 || balFac(x) <= -2) {
                if (balFac(x) == -2 && balFac(x->rc) == -1) {
                    leftRotate(x);
                }
                else if (balFac(x) == 2 && balFac(x->lc) == 1) {
                    rightRotate(x);
                }
                else if (balFac(x) == -2 && balFac(x->rc) == 1) {
                    rightRotate(x->rc);
                    leftRotate(x);
                }
                else if(balFac(x) == 2 && balFac(x->lc) == -1) {
                    leftRotate(x->lc);
                    rightRotate(x);
                }
                break;
            }
            x = x->p;
        }
    }
}

int main() {
    scanf("%d", &N);
    int t;
    for (int i = 0; i < N; i++) {
        scanf("%d", &t);
        insert(t);
    }

    printf("%d", root->data);

    return 0;
}
2018-03-16 失败的刷题 AVL树_第1张图片
image.png

送自己一朵小 Fa Fa~

你可能感兴趣的:(2018-03-16 失败的刷题 AVL树)