美文网首页
All for PAT秋考 | 1116 - 1123

All for PAT秋考 | 1116 - 1123

作者: zilla | 来源:发表于2019-08-20 22:43 被阅读0次

    涉及知识

    • 1118 并查集(模板题)
    • 1119 二叉树建树(前序、后序,唯一否?)
    • 1121 set应用,复杂度
    • 1123 AVL tree + 判断完全二叉树

    1116 - 1119

    1116 Come on! Let's C (20 分)

    水题

    #include <cstdio>
    #include <cmath>
    
    #define INF 0x3ffffff
    using namespace std;
    struct Candidate {
        int id, rank = -1;
        bool checked = false;
    } candidates[10001];
    
    int getAward(int mid) {
        int rank = candidates[mid].rank;
        if (rank == -1) return -1;
        if (!candidates[mid].checked) candidates[mid].checked = true;
        else return 0;
        if (rank == 1) return 1;
        int bound = sqrt(rank);
        for (int i = 2; i <= bound; ++i) {
            if (rank % i == 0) return 3;
        }
        return 2;
    }
    
    int main() {
        int nn;
        scanf("%d", &nn);
        int id;
        for (int i = 1; i <= nn; ++i) {
            scanf("%d", &id);
            candidates[id].id = id, candidates[id].rank = i;
        }
        int kk;
        scanf("%d", &kk);
        for (int j = 0; j < kk; ++j) {
            scanf("%d", &id);
            printf("%04d: ", id);
            switch (getAward(id)) {
                case 1: // rank 1
                    puts("Mystery Award");
                    break;
                case 2: // rank prime
                    puts("Minion");
                    break;
                case 3: // other rank
                    puts("Chocolate");
                    break;
                case -1: //not exist
                    puts("Are you kidding?");
                    break;
                case 0:
                    puts("Checked");
                    break;
            }
        }
        return 0;
    }
    

    1117 Eddington Number (25 分)

    "Eddington number", E -- that is, the maximum integer E such that it is for E days that one rides more than E miles. Eddington's own E was 87.Now given everyday's distances that one rides for N days, you are supposed to find the corresponding E (≤N).

    • ⚠️题意理解:找出N个数中,存在E个大于E的数。求最大的E。
    • 直接遍历复杂度到n^2,所以想到排序。
    • 从大到小排序,从头遍历直到当前元素不再大于已遍历过的元素个数。
    #include <cstdio>
    #include <algorithm>
    #include <functional>
    
    using namespace std;
    int nn, recs[100001]; // from 1 to nn;
    int main() {
        scanf("%d", &nn);
        for (int i = 0; i < nn; ++i) {
            scanf("%d", &recs[i]);
        }
        sort(recs, recs + nn, greater<>());
        int mmax = 0;
        while (mmax < nn && recs[mmax] > mmax + 1)
            mmax++;
        printf("%d\n", mmax);
        return 0;
    }
    

    1118 Birds in Forest (25 分)

    并查集模板题

    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    
    int uf[10001];
    
    int _find(int ii) {
        return uf[ii] < 0 ? ii : uf[ii] = _find(uf[ii]);
    }
    
    void _union(int a, int b) {
        a = _find(a);
        b = _find(b);
        if (a != b) {
            uf[a] += uf[b];
            uf[b] = a;
        }
    }
    
    int main() {
        int n_bird = -1, n_tree = 0, nn;
        fill(uf, uf + 10001, -1);
        scanf("%d", &nn);
        for (int i = 0; i < nn; ++i) {
            int cnt;
            scanf("%d", &cnt);
            if (cnt) {
                int head, temp;
                scanf("%d", &head);
                n_bird = max(n_bird, head);
                for (int j = 1; j < cnt; ++j) {
                    scanf("%d", &temp);
                    n_bird = max(n_bird, temp);
                    _union(head, temp);
                }
            }
        }
        for (int i = 1; i <= n_bird; ++i) {
            _find(i);
            if (uf[i] < 0) n_tree++;
        }
        int nq;
        scanf("%d", &nq);
        printf("%d %d\n", n_tree, n_bird);
        int b1, b2;
        for (int i = 0; i < nq; ++i) {
            scanf("%d%d", &b1, &b2);
            puts(_find(b1) == _find(b2) ? "Yes" : "No");
        }
        return 0;
    }
    

    1119 Pre- and Post-order Traversals (30 分)

    ⚠️急着上手,没有冷静分析。这递归写的,略难受。下面来分析一波——

    • 以下分析前提是树中的结点key值不重复
    1. 为什么前序、后序序列,可能不能唯一确定一棵二叉树
      • 前序: 左子树 右子树
        后序:左子树 右子树
        中序:左子树 右子树

      • 唯一确定一棵树的形态,关键在于找到根结点,并且划分开左右子树。前序、后序中任一个可以用来确定根结点,但只有中序才能根据根结点key值,找到根结点位置,划分开左右子树。
    2. 什么情况下给定前序、后序序列,二叉树形态不唯一
      • 前序:根 |左根 左 左…… | 右根 右 右……
        后序:左 左…… 左根 | 右 右…… 右根 | 根

      • 前序中,根右边挨着的X一定是子树的根,可能是左子树的根或者右子树的根。
        后序中,根左边挨着的Y一定是子树的根,可能是左子树的根或者右子树的根。

        • 若X == Y,则根只有左子树/只有右子树。但不知道究竟是左子树还是右子树。
        • 若X != Y,则X == 左根,Y == 右根,这一步左右子树的划分是唯一的。

    • 本题要求:不唯一时,随意输出一种可能的二叉树。不妨,不唯一的划分统统划给左子树。
      下面是当时的代码。。。太过走弯路= =
    #include <cstdio>
    #include <algorithm>
    #include <set>
    
    using namespace std;
    struct Node {
        int key;
        Node *lchild = NULL, *rchild = NULL;
    };
    int pre_order[31], post_order[31], nn_node, cnt = 0;
    bool _unique = true;
    
    Node *createBTree(int pre_st, int pre_ed, int post_st, int post_ed) {
        if (pre_st > pre_ed || post_st > post_ed) return NULL;
        Node *root = new Node;
        int rkey = pre_order[pre_st]; //pre_order[pre_st] = post_order[post_ed]
        root->key = rkey;
        int ltree_size = 0, bound = pre_ed - pre_st; //bound = ltree_size + rtree_size
        if (bound == 0)
            return root;
        set<int> pre_lkeys, post_lkeys;
        int lroot_pre, lroot_post, rroot_pre, rroot_post;
        int curr_type = 0, one_possible_lsize;
    
        // rtree == NULL
        lroot_pre = pre_order[pre_st + 1];
        lroot_post = post_order[post_ed - 1];
        if (lroot_pre == lroot_post) {
            one_possible_lsize = bound;
            curr_type++;
        }
    
        // ltree == NULL
        rroot_pre = pre_order[pre_st + 1];
        rroot_post = post_order[post_ed - 1];
        if (rroot_pre == rroot_post) {
            one_possible_lsize = 0;
            curr_type++;
        }
    
        //both not NULL
        if (curr_type < 2) {
            for (ltree_size = 1; ltree_size < bound; ++ltree_size) {
                pre_lkeys.insert(pre_order[pre_st + ltree_size]);
                post_lkeys.insert(post_order[post_st + ltree_size - 1]);
                if (pre_lkeys == post_lkeys) {
                    lroot_pre = pre_order[pre_st + 1];
                    lroot_post = post_order[post_st + ltree_size - 1];
                    rroot_pre = pre_order[pre_st + ltree_size + 1];
                    rroot_post = post_order[post_ed - 1];
                    if (lroot_pre == lroot_post && rroot_pre == rroot_post) {
                        curr_type++;
                        one_possible_lsize = ltree_size;
                    }
                }
                if (curr_type > 1) break;
            }
        }
        if (curr_type > 1) _unique = false;
        root->lchild = createBTree(pre_st + 1, pre_st + one_possible_lsize, post_st, post_st + one_possible_lsize - 1);
        root->rchild = createBTree(pre_st + one_possible_lsize + 1, pre_ed, post_st + one_possible_lsize, post_ed - 1);
        return root;
    }
    
    void in_order_traverse(Node *root) {
        if (root == NULL) return;
        in_order_traverse(root->lchild);
        printf("%d", root->key);
        cnt++;
        printf(cnt < nn_node ? " " : "\n");
        in_order_traverse(root->rchild);
    }
    
    int main() {
        scanf("%d", &nn_node);
        for (int i = 0; i < nn_node; ++i) {
            scanf("%d", &pre_order[i]);
        }
        for (int i = 0; i < nn_node; ++i) {
            scanf("%d", &post_order[i]);
        }
        Node *root = createBTree(0, nn_node - 1, 0, nn_node - 1);
        puts(_unique ? "Yes" : "No");
        in_order_traverse(root);
        return 0;
    }
    

    * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

    1120 - 1123

    1120 Friend Numbers (20 分)

    水题

    #include <cstdio>
    #include <set>
    
    using namespace std;
    
    int main() {
        int nn, temp;
        set<int> res;
        scanf("%d", &nn);
        for (int i = 0; i < nn; ++i) {
            scanf("%d", &temp);
            res.insert(temp / 10000 + temp / 1000 % 10 + temp / 100 % 10 + temp / 10 % 10 + temp % 10);
        }
        int size = res.size();
        printf("%d\n", size);
        for (auto &item:res) {
            printf("%d", item);
            printf(--size ? " " : "\n");
        }
        return 0;
    }
    

    1121 Damn Single (25 分)

    set基本应用,myset.find(要查找的元素) != myset.end()

    再次强调set不可sort重排序!!!定义set之后就不能再改排序规则了。
    set、map的实现都是基于 红黑树(一种平衡二叉树),插入、查找、删除复杂度均近似O(log n)。这里set的删除指的是erase(元素),erase(迭代器)为常数复杂度,还有一种iterator erase (const_iterator first, const_iterator last)。
    来自lcpl96@cnblogs
    #include <cstdio>
    #include <set>
    #include <cstring>
    
    using namespace std;
    int cp_map[100001];
    
    int main() {
        memset(cp_map, -1, sizeof(cp_map));
        int ncp, nab;
        scanf("%d", &ncp);
        int t1, t2;
        for (int i = 0; i < ncp; ++i) {
            scanf("%d%d", &t1, &t2);
            cp_map[t1] = t2;
            cp_map[t2] = t1;
        }
        set<int> res, temp_single;
        scanf("%d", &nab);
        for (int i = 0; i < nab; ++i) {
            scanf("%d", &t1);
            if (cp_map[t1] == -1)
                res.insert(t1);
            else temp_single.insert(t1);
        }
        for (auto item:temp_single) {
            if (temp_single.find(cp_map[item]) == temp_single.end()) {
                res.insert(item);
            }
        }
        int size = res.size();
        printf("%d\n", size);
        for (auto item: res) {
            printf("%05d", item);
            printf(--size ? " " : "\n");
        }
        return 0;
    }
    

    1122 Hamiltonian Cycle (25 分)

    按照题中给的定义,判断即可。

    #include <cstdio>
    
    using namespace std;
    int nn, mm;
    bool graph[201][201] = {false};
    
    int main() {
        scanf("%d%d", &nn, &mm);
        int v1, v2;
        for (int i = 0; i < mm; ++i) {
            scanf("%d%d", &v1, &v2);
            graph[v1][v2] = graph[v2][v1] = true;
        }
        int nq;
        scanf("%d", &nq);
        for (int i = 0; i < nq; ++i) {
            bool res = true;
            int len;
            scanf("%d", &len);
            if (len != nn + 1) res = false;
            bool visited[201] = {false};
            int src, pre, curr;
            scanf("%d", &src);
            pre = src;
            for (int j = 1; j < len; ++j) {
                scanf("%d", &curr);
                if (res) {
                    if (!graph[pre][curr]) {
                        res = false;
                    } else {
                        if (!visited[curr])
                            visited[curr] = true;
                        else res = false;
                    }
                }
                pre = curr;
            }
            if (src != pre) res = false;
            puts(res ? "YES" : "NO");
        }
        return 0;
    }
    

    1123 Is It a Complete AVL Tree (30 分)

    • ⚠️Node *root = NULL; 所有指针必须初始化
    • 插入后,调整中,都要及时updateHeight(),并且调整中要从子到父update
    • getHeight()、updateHeight()、getBalancingFactor(),左旋、右旋。写法见AVL tree
    #include <cstdio>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    struct Node {
        int key, height;
        Node *lchild = NULL, *rchild = NULL;
    };
    
    bool isCBT = true, isLeaf = false;
    int nn;
    
    int getHeight(Node *root) {
        return (root == NULL) ? 0 : root->height;
    }
    
    void updateHeight(Node *root) {
        root->height = max(getHeight(root->lchild), getHeight(root->rchild)) + 1;
    }
    
    int getBalancingFactor(Node *root) {
        return getHeight(root->lchild) - getHeight(root->rchild);
    }
    
    void LeftRotate(Node *&root) {
        Node *temp = root->rchild;
        root->rchild = temp->lchild;
        temp->lchild = root;
        updateHeight(root);
        updateHeight(temp);
        root = temp;
    }
    
    void RightRotate(Node *&root) {
        Node *temp = root->lchild;
        root->lchild = temp->rchild;
        temp->rchild = root;
        updateHeight(root);
        updateHeight(temp);
        root = temp;
    }
    
    
    void insertNode(Node *&root, int x) {
        if (root == NULL) {
            root = new Node;
            root->key = x;
            root->height = 1; //注意!!!root = new Node{value, 1, NULL, NULL};
            return;
        }
        if (x < root->key) {
            insertNode(root->lchild, x);
            updateHeight(root);
            if (getBalancingFactor(root) == 2) {
                if (getBalancingFactor(root->lchild) == 1) { // LL
                    RightRotate(root);
                } else { // LR
                    LeftRotate(root->lchild); // after: LL
                    RightRotate(root);
                }
            }
        } else {
            insertNode(root->rchild, x);
            updateHeight(root);
            if (getBalancingFactor(root) == -2) {
                if (getBalancingFactor(root->rchild) == -1) { // RR
                    LeftRotate(root);
                } else { // RL
                    RightRotate(root->rchild); // after: RR
                    LeftRotate(root);
                }
            }
        }
    }
    
    void levelOrder_CheckCBT(Node *root) {
        queue<Node *> mq;
        mq.push(root);
        while (!mq.empty()) {
            Node *curr = mq.front();
            mq.pop();
            if (isLeaf && (curr->lchild || curr->rchild))
                isCBT = false;
            if (!isLeaf && isCBT && !(curr->lchild && curr->rchild))
                isLeaf = true;
            if (isCBT && curr->rchild && !curr->lchild)
                isCBT = false;
            printf("%d", curr->key);
            printf((--nn) ? " " : "\n");
            if (curr->lchild) mq.push(curr->lchild);
            if (curr->rchild) mq.push(curr->rchild);
        }
    }
    
    int main() {
        int temp;
        scanf("%d", &nn);
        Node *root = NULL; //必须!!!!! 初始化为NULL
        for (int i = 0; i < nn; ++i) {
            scanf("%d", &temp);
            insertNode(root, temp);
        }
        levelOrder_CheckCBT(root);
        puts(isCBT ? "YES" : "NO");
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:All for PAT秋考 | 1116 - 1123

          本文链接:https://www.haomeiwen.com/subject/bflmsctx.html