All for PAT秋考 | 1132 - 1135

涉及知识

  • 1132 sscanf(),浮点错误
  • 1133 链表重排(cmp函数、假装重排= =)
  • 1134 图的点覆盖(stl set应用)
  • 1135 红黑树,二叉树建树,DFS

1132 Cut Integer (20 分)

喜提新的错误种类——浮点错误

  • 浮点错误

    查了一下,柳神经验丰富

  • 浮点错误原因

    若N = 1200,a = 12, b = 0,直接N%(a✖️b)就会GG……要先判0
    而且重读题目发现,cut a K digits lone integer Z into two integers of (K/2) digits long integers A and B。
    有位朋友提醒过我,PAT里k-digit的数别用int,用string存更保险,可以避免前导零导致的问题(不知此题有没有这样的卡点)。然后sprintf……以下省略。
    另外,pow函数慎用,浮点运算有精度丢失,可以先乘1.0变double
#include 
#include 
#include 
#include 

typedef long long LL;
using namespace std;

int main() {
    int nn;
    LL num;
    string str;
    cin >> nn;
    for (int i = 0; i < nn; ++i) {
        cin >> str;
        sscanf(str.data(), "%lld", &num);
        int len = str.length();
        int exp = pow(10, len / 2);
        LL aa = num / exp, bb = num % exp;
        bool res = false;
        if (aa * bb == 0) {
            printf("No\n");
            continue;
        }
        if (num % (aa * bb) == 0)
            res = true;
        puts(res ? "Yes" : "No");
    }
    return 0;
}

1133 Splitting A Linked List (25 分)

链表重排,静态链表假装重排的套路。
Node中需要addr和order用来串起来然后假装重排,cmp规则是分类(node中的kind)然后同一类的仍保持原顺序。(⚠️分类要在串成一条链时再做,而不是输入时,这个node可能根本不在链上!!!)

#include 
#include 

#define INF 0x3fffffff
using namespace std;
int head, nn, kk;
struct Node {
    int addr, next, order, kind = INF, key;
} list[100000];

bool cmp(const Node &n1, const Node &n2) {
    if (n1.kind != n2.kind) return n1.kind < n2.kind;
    return n1.order < n2.order;
}

int main() {
    scanf("%d%d%d", &head, &nn, &kk); // if(nn==6 && kk== 66) while (1); kind
    for (int i = 0; i < nn; ++i) {
        int addr, key, next;
        scanf("%d%d%d", &addr, &key, &next);
        list[addr] = Node{addr, next, INF, 3, key};
    }
    int curr = head, order = 0;
    while (curr != -1) {
        int key = list[curr].key, kind;
        if (key < 0) kind = 0;
        else if (key <= kk) kind = 1;
        else kind = 2;
        list[curr].order = ++order;
        list[curr].kind = kind;
        curr = list[curr].next;
    }
    if (order == 0) {
        puts("-1");
        return 0;
    }
    sort(list, list + 100000, cmp);
    for (int i = 0; i < order; ++i) {
        printf("%05d %d ", list[i].addr, list[i].key);
        (i + 1 < order) ? printf("%05d\n", list[i + 1].addr) : puts("-1");
    }
    return 0;
}

1134 Vertex Cover (25 分)

  • 法1:遍历边集,确定是不是边集中所有边都至少有一个结点在所给点集中。set find……、
  • 法2:降维上瘾了……图用邻接表存储。另外存边集,一条边直接高四位v1低四位v2,一个int表示了,统统放到set edges里。
    然后,给出点集时,造一个临时的边集,判断是不是 == edges……
#include 
#include 
#include 
#include 

using namespace std;
set edges;
vector graph[10001];

int main() {
    int nn, mm;
    scanf("%d%d", &nn, &mm);
    for (int i = 0; i < mm; ++i) {
        int a, b;
        scanf("%d%d", &a, &b);
        edges.insert(min(a, b) * 10000 + max(a, b));
        graph[a].emplace_back(b);
        graph[b].emplace_back(a);
    }
    int nq;
    scanf("%d", &nq);
    for (int j = 0; j < nq; ++j) {
        int num;
        set temp;
        scanf("%d", &num);
        for (int i = 0; i < num; ++i) {
            int v1;
            scanf("%d", &v1);
            for (auto v2:graph[v1]) {
                temp.insert(min(v1, v2) * 10000 + max(v1, v2));
            }
        }
        puts(temp == edges ? "Yes" : "No");
    }
    return 0;
}

1135 Is It A Red-Black Tree (30 分)

红黑树与AVL树

There is a kind of balanced binary search tree named red-black tree in the data structure. It has the following 5 properties:
(1) Every node is either red or black.
(2) The root is black. (直接看先序第一个的颜色判断就好哈)
(3) Every leaf (NULL) is black.
(4) If a node is red, then both its children are black.
(5) For each node, all simple paths from the node to descendant leaves contain the same number of black nodes.
红黑树不是AVL树,不要求左子树右子树高度差不超过1。红黑树和AVL树都属于自平衡二叉搜索树

  • 柳神的题解

    先按照先序和大小关系建树(非递归),再分别用2个递归函数去check条件4、5

  • 我的方法

    1. 按照中序(排好序的序列就是二叉查找树的中序呀)、先序递归建树,在建树时做条件4的判断。
    2. 判断根是否是黑色,从根部DFS一波判断是否满足条件5。。。(因为已经check过满足条件4,只要确定从root到任意叶子的简单路径经过相同数量的黑色结点就好)
#include 
#include 
#include 

using namespace std;
struct Node {
    int color;
    Node *lchild = NULL, *rchild = NULL;
};

bool cmp(const int a, const int b) {
    return abs(a) < abs(b);
}

int nn, pre_order[31], in_order[31];
bool isRBT;

Node *createTree(int pre_st, int pre_ed, int in_st, int in_ed) {
    if (pre_st > pre_ed || in_st > in_ed) return NULL;
    if (pre_st == pre_ed && in_st == in_ed) {
        int key = pre_order[pre_st], color = 1;
        if (key < 0) {
            color = -1;
        }
        return new Node{color, NULL, NULL};
    }
    int rkey = pre_order[pre_st], pos = -1, lsize;
    for (int i = in_st; i <= in_ed; ++i) {
        if (in_order[i] == rkey) {
            pos = i;
            lsize = i - in_st;
        }
    }
    Node *root = new Node;
    root->color = rkey < 0 ? -1 : 1;
    root->lchild = createTree(pre_st + 1, pre_st + lsize, in_st, pos - 1);
    root->rchild = createTree(pre_st + lsize + 1, pre_ed, pos + 1, in_ed);
    if (root->color == -1 &&
        ((root->lchild && root->lchild->color != 1)
         || (root->rchild && root->rchild->color != 1)))
        isRBT = false;
    return root;
}

int curr_cnt = 0;

void DFS(Node *root, int cnt) {
    if (root == NULL) {
        if (curr_cnt == 0) curr_cnt = cnt;
        else if (curr_cnt != cnt) isRBT = false;
        return;
    }
    int extra = (root->color == 1) ? 1 : 0;
    DFS(root->lchild, cnt + extra);
    DFS(root->rchild, cnt + extra);
}

int main() {
    int test;
    scanf("%d", &test);
    for (int i = 0; i < test; ++i) {
        scanf("%d", &nn);
        for (int j = 0; j < nn; ++j) {
            scanf("%d", &pre_order[j]);
            in_order[j] = pre_order[j];
        }
        isRBT = true;
        sort(in_order, in_order + nn, cmp);
        Node *root = createTree(0, nn - 1, 0, nn - 1);
        if (isRBT && root->color == -1) isRBT = false;
        if (isRBT) {
            curr_cnt = 0;
            DFS(root, 0);
        }
        puts(isRBT ? "Yes" : "No");
    }
    return 0;
}

你可能感兴趣的:(All for PAT秋考 | 1132 - 1135)