← Back to Blog

2026暑假做题记录

2026.8-2026.9.6

2026.8.27

消磨了一个暑假到快结束的时候终于开始复健cpp和数算了。经过几个月agent的工作感觉自己的大脑变得平滑。暑假忙了两个月也没干出什么,有种修为散尽的感觉(瘫)

宝藏二叉树

树形dp。写一半想起来上学期做过。

#include<bits/stdc++.h>
using namespace std;
int n;
int main(){
    scanf("%d",&n);
    int dp1[n+1],dp2[n+1],a[n+1];
    memset(dp1,0,sizeof(dp1));//选
    memset(dp2,0,sizeof(dp2));//不选
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        dp1[i]=a[i];
    }
    for(int i=n;i>=1;i--){
        int l=i<<1,r=i<<1|1;
        if(l<=n){
            dp1[i]+=dp2[l];
            dp2[i]+=max(dp1[l],dp2[l]);
        }
        if(r<=n){
            dp1[i]+=dp2[r];
            dp2[i]+=max(dp1[r],dp2[r]);
        }
    }
    printf("%d",max(dp1[1],dp2[1]));
    return 0;
}

文本二叉树

标了m但有点难度。 关键点一个在于星号可以标记是否有左儿子,因此对每个节点增加一个cnt来记录已经处理了几个儿子。另一个在于开一个数组记录最近的第i层的节点。

#include<bits/stdc++.h>
using namespace std;
struct TreeNode{
    char val;
    int left=-1;
    int right=-1;
    int cnt=0;//已处理的孩子数
};
TreeNode tree[205];
int n,m;
void preorder(int root){
    if(root==-1) return;
    printf("%c",tree[root].val);
    preorder(tree[root].left);
    preorder(tree[root].right);
}
void inorder(int root){
    if(root==-1) return;
    inorder(tree[root].left);
    printf("%c",tree[root].val);
    inorder(tree[root].right);
}
void postorder(int root){
    if(root==-1) return;
    postorder(tree[root].left);
    postorder(tree[root].right);
    printf("%c",tree[root].val);
}
int main(){
    scanf("%d",&n);
    for(int t=1;t<=n;t++){
        m=0;
        int last[105];//最近的第i层节点
        for(int i=0;i<105;i++){
            last[i]=-1;
        }
        for(int i=1;i<=200;i++){
            tree[i].val=' ';
            tree[i].left=-1;
            tree[i].right=-1;
        }
        int root=-1;
        vector<pair<int,int>> nodes;
        char line[105]=" ";
        while(strcmp(line,"0")!=0){
            scanf("%s",line);
            if(strcmp(line,"0")==0) break;
            int level=0;
            while(level<strlen(line)&&line[level]=='-'){
                level++;
            }
            char val=line[level];
            if(level==0){
                tree[m++]={val};
                root=0;
                last[level]=0;
                continue;
            }
            int parent=last[level-1];
            if(val=='*'){
                tree[parent].cnt++;
            }
            else{
                tree[m++]={val};
                if(tree[parent].cnt==0){
                    tree[parent].left=m-1;
                }
                else{
                    tree[parent].right=m-1;
                }
                tree[parent].cnt++;
                last[level]=m-1;
            }
        }
        preorder(root);
        printf("\n");
        postorder(root);
        printf("\n");
        inorder(root);
        printf("\n\n");
    }
}

【模板】最近公共祖先(LCA)

复健一下倍增lca

#include<bits/stdc++.h>
using namespace std;
int n,m,s;
const int N=1e6+5;
vector<int> e[N];
int f[N][33],dep[N];
void dfs(int u,int fa){
    dep[u]=dep[fa]+1;
    f[u][0]=fa;
    for(auto v:e[u]){
        if(v==fa) continue;
        dfs(v,u);
    }
}
int lca(int x,int y){
    if(dep[x]<dep[y]) swap(x,y);
    for(int i=22;i>=0;i--){
        if(dep[f[x][i]]>=dep[y]) x=f[x][i];
    }
    if(x==y) return x;
    for(int i=22;i>=0;i--){
        if(f[x][i]!=f[y][i]){
            x=f[x][i];
            y=f[y][i];
        }
    }
    return f[x][0];
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin>>n>>m>>s;
    for(int i=1;i<n;i++){
        int x,y;
        cin>>x>>y;
        e[x].push_back(y);
        e[y].push_back(x);
    }
    dfs(s,0);
    for(int j=1;(1<<j)<=n;j++){
        for(int i=1;i<=n;i++){
            f[i][j]=f[f[i][j-1]][j-1];
        }
    }
    for(int i=1;i<=m;i++){
        int x,y;
        cin>>x>>y;
        cout<<lca(x,y)<<endl;
    }
    return 0;
}

填充每个节点的下一个右侧节点指针

层序遍历

#include<bits/stdc++.h>
using namespace std;
// Definition for a Node.
class Node {
public:
    int val;
    Node* left;
    Node* right;
    Node* next;

    Node() : val(0), left(NULL), right(NULL), next(NULL) {}

    Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}

    Node(int _val, Node* _left, Node* _right, Node* _next)
        : val(_val), left(_left), right(_right), next(_next) {}
};


class Solution {
public:
    Node* connect(Node* root) {
        if(root==nullptr) return root;
        queue<Node*> q;
        q.push(root);
        while(!q.empty()){
            int n=q.size();
            for(int i=0;i<n;i++){
                Node *node=q.front();
                q.pop();
                if(i<n-1) node->next=q.front();
                if(node->left) q.push(node->left);
                if(node->right) q.push(node->right);
            }
        }
        return root;
    }
};

// 根据层序数组创建完美二叉树。
Node* buildTree(const vector<int>& values) {
    if (values.empty()) return nullptr;

    vector<Node*> nodes;
    for (int value : values) {
        nodes.push_back(new Node(value));
    }

    for (int i = 0; i < (int)nodes.size(); ++i) {
        int leftIndex = 2 * i + 1;
        int rightIndex = 2 * i + 2;
        if (leftIndex < (int)nodes.size()) {
            nodes[i]->left = nodes[leftIndex];
        }
        if (rightIndex < (int)nodes.size()) {
            nodes[i]->right = nodes[rightIndex];
        }
    }
    return nodes[0];
}

// 按照 LeetCode 的格式,沿 next 指针输出每一层。
void printByNext(Node* root) {
    if (root == nullptr) {
        cout << "[]\n";
        return;
    }

    cout << '[';
    Node* levelStart = root;
    bool first = true;
    while (levelStart != nullptr) {
        for (Node* current = levelStart; current != nullptr;
             current = current->next) {
            if (!first) cout << ',';
            cout << current->val;
            first = false;
        }
        cout << ",#";
        levelStart = levelStart->left;
    }
    cout << "]\n";
}

void deleteTree(Node* root) {
    if (root == nullptr) return;
    deleteTree(root->left);
    deleteTree(root->right);
    delete root;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    Solution solution;

    // 示例 1:root = [1,2,3,4,5,6,7]
    Node* root1 = buildTree({1, 2, 3, 4, 5, 6, 7});
    solution.connect(root1);
    printByNext(root1);  // [1,#,2,3,#,4,5,6,7,#]
    deleteTree(root1);

    // 示例 2:root = []
    Node* root2 = buildTree({});
    solution.connect(root2);
    printByNext(root2);  // []
    deleteTree(root2);

    return 0;
}

2026.9.2

Huffman编码树

#include<bits/stdc++.h>
using namespace std;
priority_queue<int,vector<int>,greater<int>> q;
int n;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin>>n;
    int x;
    for(int i=0;i<n;i++){
        cin>>x;
        q.push(x);
    }
    int sum=0;
    while(q.size()>1){
        int x=q.top();
        q.pop();
        int y=q.top();
        q.pop();
        sum+=(x+y);
        q.push(x+y);
    }
    cout<<sum<<endl;
    return 0;
}

最短的一篇做题记录出现了……

唉其实我真的挺喜欢这门课的,但是vibe coding真的太好用了你们懂吗,就是我一看到gpt我就不对劲了,我就想一直点,我也不想看手册了,也不想打开vscode了,oj我碰都不碰,我就想开codex,我一天不碰vibe coding我就像身上有蚂蚁在爬一样你知道吗.有一天我就想打开vscode我自己编个hello world,回过神发现我在给codex开vscode的权限.太幸福了你们知道吗,就像vscode里写东西,逛github是苦闷的生活,只有vibe coding的时候我才是活着的,我才能什么都做得到.我感觉自己这辈子没有gpt已经不行了,现在就是后悔,很后悔,要是能早点知道碰了vibe coding会这样我肯定这辈子都不会开codex一下的.对了你要不要看我最近vibe coding的个人工作台

DISCUSSION

Comments

Sign in with GitHub to join the conversation.