【CSP】2020-12-3 带配额的文件系统 100分完整代码 最长的大模拟 使用指针优化数据结构

索引

历年CSP认证考试真题题解总汇持续更新

2020-12-3 带配额的文件系统 最长的大模拟 使用指针优化数据结构

这题可以说是最长第三题了, 但是逻辑并不是非常的复杂,关键是使用一个好的数据结构和编程的思想,越是复杂的题就越是要暴力,这种情况下即使有一些重复的计算也没关系,有一个简洁清晰的逻辑最为重要。 这种情况下就是要用时间换取逻辑的清晰了。

写这题的经历非常曲折差不多写了快三版才写到100分,而且其中的一些问题还是没有找到,如果有大神有思路希望告知,最后是参考了别人的代码,修改了最后一版,才拿到100分,考试遇到了这题基本上就g了。

可能做题的意义就是见识这些大风大浪。

思路

除去题目给出要求,还要注意一下几点

新建文件的指令

  1. 指令执行不成功,文件系统不能有变化
  2. 新建文件要在路径上所有的目录增加大小
  3. 注意新建文件的时候要看,原本的文件有没有存在,目录增加的大小要根据原本的文件大小算

删除文件的指令

  1. 如果删除的是文件夹 则上级的目录的大小要删除文件夹的所有后代大小

配额指令

这个没啥比较简单,按题目来就行

遇到的问题(学到的东西)

  1. 数据结构选取的有问题,导致逻辑异常复杂

一开始想着用一个邻接表存文件之间的关系,然后用数组存文件的数据,然后用索引来建立两者的关系,然后我虽然清楚其中的逻辑,但是写代码异常的难受,就是每个模块之间耦合性非常的强,导致出问题,一出一长串,最后出现的错误,没有很长的测试数据,都找不到bug出在哪里,所以以后要尽量避免这种复杂逻辑的,用一些直观的数据结构更好。

总共写了250行。

如果代码写了超过了200行那么一定是逻辑有问题。

最后这一版过了acwing 7/15个测试数据,在官网拿到了40分

在这里插入图片描述

image-20240322213821258

  1. 看了别人的思路,使用了指针的数据结构

改用了指针的数据结构,但是判断逻辑几乎没有改。使用了指针的结构方便了不少,比之前的数据结构方便不少。但是尤其是新建文件的逻辑,耦合度非常的高,要是修一个bug得好久,并且就像是的机器学习过拟合一样,只能适用于特殊情况,出了问题还得再加特殊情况,一直打补丁真的很恶心,最后这一版也是改到了

acwing 15/15个测试点 csp官网40分

在这里插入图片描述

在这里插入图片描述

期间也是出现了一些问题

  • 使用指针怎么申请空间(不能是直接用声明变量的形式声明)

错误的:

	if (i >= fs.size() - 1) // 还未创建
        {
            struct dfile temp;
            if (i == path.size() - 1)
            {
                temp.size = file_size;
                temp.type = 0;
            }
            else
            {
                temp.child_size += t_file_size;
                temp.dir_size += i == path.size() - 2 ? t_file_size : 0;
                temp.type = 1;
           }
        // 建立索引
        fs.back()->child[path[i]] = &temp;
        

这样申请空间会导致,下次temp再用的时候这个就会被释放,建立了索引也没用,数据也会丢失

正确的:使用new申请空间

        if (i >= fs.size() - 1) // 还未创建
        {
            struct dfile *temp = new dfile(1);
            if (i == path.size() - 1)
            {
                temp->size = file_size;
                temp->type = 0;
            }
            else
            {
                temp->child_size += t_file_size;
                temp->dir_size += i == path.size() - 2 ? t_file_size : 0;
                temp->type = 1;
            }
            // 建立索引
            fs.back()->child[path[i]] = temp;
  • 初值的问题

虽然设置的结构体是全局变量,但是结构体内部的变量的值还是需要设置初值的。

struct dfile
{
    long long size = 0;
    long long dir_size = 0;    //
    long long child_size = 0;  // 后代大小
    long long dir_limit = 0;   // 目录配额
    long long child_limit = 0; // 孩子配额
    bool isDir = 0;            // 1是目录 0是文件
    map<string, struct dfile *> child;
    dfile(int t) : isDir(t) {}
};
  1. 优化了新建文件的逻辑

使用了耦合度比较低的逻辑,虽然要多花一些时间,但是逻辑非常清晰,然后过了样例后,直接就100分了。
在这里插入图片描述

这里面也学会了一些用法

  • string的一些方法
vector<string> split(const string &s, const string &c = "")
{
    vector<string> res;
    for (long long i = 0, j = 0; i < s.size(); i = j + 1)
    {
        j = s.find(c, i);
        if (j == -1)
            j = s.size();
        res.push_back(s.substr(i, j - i));
    }
    return res;
}

从i开始找到c字符串的下标,如果没有找到则返回-1

s.find(c,i)

分割字符串 从i开始返回j-i个长度的字符串

s.substr(i,j-i)
  • 空指针是nullptr
    for (int i = 1; i < path.size() && p; i++)
    {
        // 向前判断判断i-1的时候的p 不会判断最后一个p(文件的指针)
        if (!p->isDir or (p->child_limit && p->child_size + sz > p->child_limit) or (i == path.size() - 1 && p->dir_limit && p->dir_size + sz > p->dir_limit))
            return false;
        p = p->child.count(path[i]) ? p->child[path[i]] : nullptr;
    }

可以直接判断 &&p 判断p为不为空

  • c++可以直接使用 and or等

在C语言ios646.h头文件种定义了关于and、or、not逻辑运算符。

and可以代替&&

or可以替代||

not可以替代!

40分stl代码

#include <bits/stdc++.h>
using namespace std;
struct file
{
    string name;
    long long size;

    long long dir_size;
    long long child_size;
    long long dir_limit;
    long long child_limit;
    int type = -1; // 0是普通文件 1是目录文件
    int to_paths;  // 用于寻找文件内的索引
} f[2000001];
long long top;
map<long long, vector<long long>> paths;
long long indexes; // 提供一个不重复的索引
vector<string> convert_string_path(string file_path)
{
    vector<string> res;
    string temp = "";
    for (int i = 1; i < file_path.size(); i++)
    {
        if (file_path[i] != '/')
        {
            temp += file_path[i];
        }
        else
        {
            res.push_back(temp);
            temp.clear();
        }
    }
    if (!temp.empty())
        res.push_back(temp);
    return res;
}
int find_file_from_dir(long long dir, string name) // 返回文件位置
{
    vector<long long> temp = paths[f[dir].to_paths];
    for (int i = 0; i < temp.size(); i++)
    {
        if (name == f[temp[i]].name)
        {
            return temp[i];
        }
    }
    return -1;
}
bool deal_creat(string file_path, long long file_size) // 创建普通文件
{
    vector<string> path = convert_string_path(file_path);
    vector<long long> real_path;
    bool exist = false; // 这个文件是不是已经存在

    if (f[0].child_limit && f[0].child_size + file_size > f[0].child_limit)
        return false;
    if (f[0].dir_limit && path.size() == 1 && f[0].dir_size + file_size > f[0].dir_limit)
        return false;

    long long dir = 0; // 先从根目录开始
    for (int i = 0; i < path.size(); i++)
    {
        long long file_locate = find_file_from_dir(dir, path[i]);
        if (file_locate == -1)
        {
            // 先申请一个目录的位置
            dir = top;
            real_path.push_back(top++);
        }
        else
        {
            if (i == path.size() - 1) // 如果是最后一个 则是文件不是目录
            {
                if (f[file_locate].type == 1)
                {
                    return false;
                }
                else // 替换这个文件
                {
                    exist = true;
                    real_path.push_back(file_locate);
                }
            }
            else // 找到了文件看看是不是目录
            {
                if (f[file_locate].type == 0) // 如果是普通文件
                {
                    return false;
                }
                else // 如果该目录存在
                {
                    real_path.push_back(file_locate);
                    dir = file_locate;
                }
            }
        }
    }
    long long t_file_size = file_size;
    if (exist)
        t_file_size = file_size - f[real_path[real_path.size() - 1]].size;
    for (int i = 0; i < real_path.size() - 1; i++)
    {
        if (f[real_path[i]].child_limit && f[real_path[i]].child_size + t_file_size > f[real_path[i]].child_limit)
            return false;
        if (f[real_path[i]].dir_limit && i == real_path.size() - 2 && f[real_path[i]].dir_size + t_file_size > f[real_path[i]].dir_limit)
            return false;
    }
    dir = 0;
    if (path.size() == 1)
        f[0].dir_size += t_file_size;
    f[0].child_size += t_file_size;
    for (int i = 0; i < path.size(); i++)
    {
        if (f[real_path[i]].type == -1) // 还未创建
        {
            f[real_path[i]].name = path[i];
            if (i == path.size() - 1)
            {
                f[real_path[i]].size = file_size;
                f[real_path[i]].type = 0;
            }
            else
            {
                f[real_path[i]].child_size += t_file_size;
                f[real_path[i]].dir_size += i == path.size() - 2 ? t_file_size : 0;

                f[real_path[i]].to_paths = indexes++; // 为这个文件构建索引
                f[real_path[i]].type = 1;
            }
            // 建立索引
            paths[dir].push_back(real_path[i]);
        }
        else // 如果已经创建了
        {
            if (i == path.size() - 1)
            {
                f[real_path[i]].size = file_size;
            }
            else
            {
                f[real_path[i]].child_size += t_file_size;
                f[real_path[i]].dir_size += i == path.size() - 2 ? t_file_size : 0;
            }
        }
        dir = f[real_path[i]].to_paths;
    }
    return true;
}
bool deal_remove(string file_path)
{
    vector<string> path = convert_string_path(file_path);
    vector<long long> real_path;
    real_path.push_back(0); // 把根目录添加
    int dir = 0;
    for (int i = 0; i < path.size(); i++)
    {
        long long file_locate = find_file_from_dir(dir, path[i]);
        if (file_locate == -1)
        {
            return true;
        }
        real_path.push_back(file_locate);
        dir = file_locate;
    }

    // 删去索引
    int file_locate = f[real_path[real_path.size() - 2]].to_paths;
    vector<long long> temp = paths[file_locate];
    for (int i = 0; i < temp.size(); i++)
    {
        if (temp[i] == real_path[real_path.size() - 1])
        {
            paths[file_locate].erase(paths[file_locate].begin() + i);
            break;
        }
    }
    int type = f[real_path[real_path.size() - 1]].type;
    if (type == 1)
    {
        paths.erase(f[real_path[real_path.size() - 1]].to_paths);
        // 删除占用
        long long file_size = f[real_path[real_path.size() - 1]].child_size;
        for (int i = 0; i < real_path.size() - 1; i++)
        {
            f[real_path[i]].child_size -= file_size;
        }
    }
    else
    {
        // 删除占用
        long long file_size = f[real_path[real_path.size() - 1]].size;
        for (int i = 0; i < real_path.size() - 1; i++)
        {
            f[real_path[i]].child_size -= file_size;
            if (i == real_path.size() - 2)
                f[real_path[i]].dir_size -= file_size;
        }
    }
    return true;
}
long long get_sum_size(int dir)
{
    vector<long long> temp = paths[f[dir].to_paths];
    long long sum = 0;
    for (auto item : temp)
    {
        if (f[item].type == 0)
        {
            sum += f[item].size;
        }
        else if (f[item].type == 1)
        {
            sum += get_sum_size(item);
        }
    }
    return sum;
}
bool deal_q(string file_path, long long ld, long long lr)
{
    long long dir = 0;
    vector<string> path = convert_string_path(file_path);
    vector<long long> real_path;
    real_path.push_back(0);
    for (int i = 0; i < path.size(); i++)
    {
        long long file_locate = find_file_from_dir(dir, path[i]);
        if (file_locate == -1)
            return false;
        if (f[file_locate].type == 0) // 如果不是目录文件
            return false;
        real_path.push_back(file_locate);
        dir = file_locate;
    }
    long long pos = real_path[real_path.size() - 1];
    if (ld != 0) // 检查孩子文件的大小是不是超过限制了
    {
        vector<long long> temp = paths[f[pos].to_paths];
        long long sum = 0;
        for (int i = 0; i < temp.size(); i++)
        {
            if (f[temp[i]].type == 0)
            {
                sum += f[temp[i]].size;
            }
        }
        if (sum > ld) // 检查后代文件的总和是不是超过了限制
            return false;
    }
    if (lr != 0)
    {
        long long sum = get_sum_size(pos);
        if (sum > lr)
            return false;
    }
    f[pos].child_limit = lr;
    f[pos].dir_limit = ld;
    return true;
    // f[real_path[real_path.size() - 1]].child_limit
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    // freopen("1.txt", "r", stdin);
    int n;
    cin >> n;
    // 初始化根目录
    f[0].name = "";
    f[0].type = 1;
    f[0].to_paths = indexes++;
    top++;
    for (int i = 0; i < n; i++)
    {
        string type;
        cin >> type;
        if (type == "C")
        {
            string file_path;
            long long file_size;
            cin >> file_path >> file_size;
            if (deal_creat(file_path, file_size))
                cout << "Y" << endl;
            else
                cout << "N" << endl;
        }
        if (type == "R")
        {
            string file_path;
            cin >> file_path;
            if (deal_remove(file_path))
                cout << "Y" << endl;
        }
        if (type == "Q")
        {
            string file_path;
            long long ld, lr;
            cin >> file_path >> ld >> lr;
            if (deal_q(file_path, ld, lr))
                cout << "Y" << endl;
            else
                cout << "N" << endl;
        }
    }
    return 0;
}

acwing 15/15 csp官网40分代码

#include <bits/stdc++.h>
using namespace std;
struct dfile
{
    long long size;
    long long dir_size = 0;
    long long child_size = 0;
    long long dir_limit = 0;
    long long child_limit = 0;
    int type = -1; // 0是普通文件 1是目录文件
    map<string, struct dfile *> child;
    dfile(int t) : type(t) {}
};
struct dfile root(1);
vector<string> convert_string_path(string file_path)
{
    vector<string> res;
    string temp = "";
    for (int i = 1; i < file_path.size(); i++)
    {
        if (file_path[i] != '/')
        {
            temp += file_path[i];
        }
        else
        {
            res.push_back(temp);
            temp.clear();
        }
    }
    if (!temp.empty())
        res.push_back(temp);
    return res;
}
bool deal_creat(string file_path, long long file_size) // 创建普通文件
{
    vector<string> path = convert_string_path(file_path);
    bool exist = false; // 这个文件是不是已经存在

    struct dfile *p = &root;
    vector<struct dfile *> fs;
    fs.push_back(p);
    bool newdir = false; // 记录有没有新的文件夹产生
    // 检查目录是不是被文件占用
    for (int i = 0; i < path.size() - 1; i++)
    {
        if (p->child.count(path[i]))
        {
            // 找到了文件看看是不是目录
            struct dfile *temp = p->child[path[i]];
            if (temp->type == 0) // 如果是普通文件
                return false;
            p = temp;
            fs.push_back(p);
        }
        else
            newdir = true;
    }
    // 文件名是不是被目录占用
    // 只有没有新建文件夹的时候才检查
    if (!newdir)
    {
        struct dfile *last = fs.back();
        if (last->child.count(path.back()))
        {
            if (last->child[path.back()]->type == 1)
                return false;
            exist = true;
            fs.push_back(last->child[path.back()]);
        }
        else
        {
            fs.push_back(new dfile(0));
        }
    }
    // 判断大小限制是不是符合
    long long t_file_size = file_size;
    if (exist)
        t_file_size = file_size - fs.back()->size;

    for (int i = 0; i < fs.size(); i++)
    {
        if (fs[i]->type == 1 && fs[i]->child_limit && fs[i]->child_size + t_file_size > fs[i]->child_limit)
            return false;
        if (fs[i]->type == 1 && !newdir && fs[i]->dir_limit && i == fs.size() - 2 && fs[i]->dir_size + t_file_size > fs[i]->dir_limit)
            return false;
    }

    // 给路径上的文件夹增加大小
    fs[0]->child_size += t_file_size;
    if (path.size() == 1)
        fs[0]->dir_size += t_file_size;
    for (int i = 0; i < path.size(); i++)
    {
        if (i >= fs.size() - 1) // 还未创建
        {
            struct dfile *temp = new dfile(1);
            if (i == path.size() - 1)
            {
                temp->size = file_size;
                temp->type = 0;
            }
            else
            {
                temp->child_size += t_file_size;
                temp->dir_size += i == path.size() - 2 ? t_file_size : 0;
                temp->type = 1;
            }
            // 建立索引
            fs.back()->child[path[i]] = temp;
            fs.push_back(temp);
        }
        else // 如果已经创建了
        {
            if (i == path.size() - 1)
            {
                fs[i + 1]->size = file_size;
                fs[i]->child[path[i]] = fs[i + 1];
            }
            else
            {
                fs[i + 1]->child_size += t_file_size;
                fs[i + 1]->dir_size += i == path.size() - 2 ? t_file_size : 0;
            }
        }
    }
    return true;
}
bool deal_remove(string file_path)
{
    vector<string> path = convert_string_path(file_path);
    vector<struct dfile *> fs;
    fs.push_back(&root);

    // 判断路径存不存在
    struct dfile *p = &root;
    for (int i = 0; i < path.size(); i++)
    {
        if (!p->child.count(path[i]))
            return true;
        p = p->child[path[i]];
        fs.push_back(p);
    }

    // 删去索引
    fs[fs.size() - 2]->child.erase(path.back());
    // 删除占用
    int type = fs.back()->type;
    if (type == 1) // 如果是文件夹
    {
        // 删除文件夹占用
        long long file_size = fs.back()->child_size;
        for (int i = 0; i < fs.size() - 1; i++)
        {
            fs[i]->child_size -= file_size;
        }
    }
    else
    {
        // 删除文件占用
        long long file_size = fs.back()->size;
        for (int i = 0; i < fs.size() - 1; i++)
        {
            fs[i]->child_size -= file_size;
            if (i == fs.size() - 2)
                fs[i]->dir_size -= file_size;
        }
    }
    return true;
}
bool deal_q(string file_path, long long ld, long long lr)
{

    vector<string> path = convert_string_path(file_path);
    struct dfile *p = &root;
    vector<struct dfile *> fs;
    fs.push_back(p);
    for (int i = 0; i < path.size(); i++)
    {
        if (!p->child.count(path[i])) // 如果没有找到
            return false;
        if (p->child[path[i]]->type == 0) // 如果不是目录文件
            return false;
        p = p->child[path[i]];
        fs.push_back(p);
    }
    struct dfile *dir = fs.back();
    if (ld != 0) // 检查孩子文件的大小是不是超过限制了
    {
        if (dir->dir_size > ld)
            return false;
    }
    if (lr != 0) // 检查后代文件的总和是不是超过了限制
    {
        if (dir->child_size > lr)
            return false;
    }
    dir->child_limit = lr;
    dir->dir_limit = ld;
    return true;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    // freopen("1.txt", "r", stdin);
    int n;
    cin >> n;
    // 初始化根目录
    root.type = 1;

    for (int i = 0; i < n; i++)
    {
        string type;
        cin >> type;
        if (type == "C")
        {
            string file_path;
            long long file_size;
            cin >> file_path >> file_size;
            if (deal_creat(file_path, file_size))
                cout << "Y" << endl;
            else
                cout << "N" << endl;
        }
        if (type == "R")
        {
            string file_path;
            cin >> file_path;
            if (deal_remove(file_path))
                cout << "Y" << endl;
        }
        if (type == "Q")
        {
            string file_path;
            long long ld, lr;
            cin >> file_path >> ld >> lr;
            if (deal_q(file_path, ld, lr))
                cout << "Y" << endl;
            else
                cout << "N" << endl;
        }
    }
    return 0;
}

100分完整代码

#include <bits/stdc++.h>
using namespace std;
struct dfile
{
    long long size = 0;
    long long dir_size = 0;    //
    long long child_size = 0;  // 后代大小
    long long dir_limit = 0;   // 目录配额
    long long child_limit = 0; // 孩子配额
    bool isDir = 0;            // 1是目录 0是文件
    map<string, struct dfile *> child;
    dfile(int t) : isDir(t) {}
};
struct dfile root(1);
vector<string> split(const string &s, const string &c = "")
{
    vector<string> res;
    for (long long i = 0, j = 0; i < s.size(); i = j + 1)
    {
        j = s.find(c, i);
        if (j == -1)
            j = s.size();
        res.push_back(s.substr(i, j - i));
    }
    return res;
}
int get_file_size(vector<string> path)
{
    struct dfile *p = &root;
    for (int i = 1; i < path.size() && p; i++)
    {
        p = p->child.count(path[i]) ? p->child[path[i]] : nullptr;
    }
    return p and !p->isDir ? p->size : 0;
}
bool can_create(vector<string> path, long long sz)
{
    struct dfile *p = &root;
    for (int i = 1; i < path.size() && p; i++)
    {
        // 向前判断判断i-1的时候的p 不会判断最后一个p(文件的指针)
        if (!p->isDir or (p->child_limit && p->child_size + sz > p->child_limit) or (i == path.size() - 1 && p->dir_limit && p->dir_size + sz > p->dir_limit))
            return false;
        p = p->child.count(path[i]) ? p->child[path[i]] : nullptr;
    }
    return !p or !p->isDir; // 如果没有文件、文件夹占用文件名 或者 是文件占用文件名
}
bool deal_creat(vector<string> path, long long file_size) // 创建普通文件
{
    int sz = file_size - get_file_size(path);

    if (!can_create(path, sz))
        return false;
    struct dfile *p = &root;
    for (int i = 1; i < path.size() - 1 /*剩下最后一个是文件*/; i++)
    {
        p->child_size += sz;
        if (!p->child.count(path[i]))
            p->child[path[i]] = new dfile(1);
        p = p->child[path[i]];
    }
    // p是文件的上一级
    p->child_size += sz, p->dir_size += sz;
    // 判断文件是不是存在
    if (!p->child.count(path.back()))
        p->child[path.back()] = new dfile(0);

    // 设置大小 注意这里不管是新建的还是覆盖的都是+=sz
    p->child[path.back()]->size += sz;
    return true;
}
bool deal_remove(vector<string> path)
{
    vector<struct dfile *> fs;
    fs.push_back(&root);

    // 判断路径存不存在
    struct dfile *p = &root;
    for (int i = 1; i < path.size(); i++)
    {
        if (!p->child.count(path[i]))
            return true;
        p = p->child[path[i]];
        fs.push_back(p);
    }

    // 删去索引
    fs[fs.size() - 2]->child.erase(path.back());
    // 删除占用
    bool type = fs.back()->isDir;
    if (type) // 如果是文件夹
    {
        // 删除文件夹占用
        long long file_size = fs.back()->child_size;
        for (int i = 0; i < fs.size() - 1; i++)
        {
            fs[i]->child_size -= file_size;
        }
    }
    else
    {
        // 删除文件占用
        long long file_size = fs.back()->size;
        for (int i = 0; i < fs.size() - 1; i++)
        {
            fs[i]->child_size -= file_size;
            if (i == fs.size() - 2)
                fs[i]->dir_size -= file_size;
        }
    }
    return true;
}
bool deal_q(vector<string> path, long long ld, long long lr)
{
    struct dfile *p = &root;
    for (int i = 1; i < path.size(); i++)
    {
        if (!p->child.count(path[i])) // 如果没有找到
            return false;
        if (p->child[path[i]]->isDir == 0) // 如果不是目录文件
            return false;
        p = p->child[path[i]];
    }
    struct dfile *dir = p;
    if (ld && dir->dir_size > ld) // 检查孩子文件的大小是不是超过限制了
        return false;
    if (lr && dir->child_size > lr) // 检查后代文件的总和是不是超过了限制
        return false;
    dir->child_limit = lr;
    dir->dir_limit = ld;
    return true;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    // freopen("1.txt", "r", stdin);
    int n;
    cin >> n;

    for (int i = 0; i < n; i++)
    {
        string type, file_path;
        cin >> type >> file_path;
        vector<string> path = split(file_path, "/");
        if (type == "C")
        {
            long long file_size;
            cin >> file_size;
            cout << (deal_creat(path, file_size) ? "Y" : "N") << endl;
        }
        if (type == "R")
        {
            deal_remove(path);
            cout << "Y" << endl;
        }
        if (type == "Q")
        {
            long long ld, lr;
            cin >> ld >> lr;
            cout << (deal_q(path, ld, lr) ? "Y" : "N") << endl;
        }
    }
    return 0;
}
  • 41
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值