1 条题解

  • 0
    @ 2025-10-16 11:13:30

    题解说明

    问题背景:
    这是一个模拟数据结构操作的程序。程序中每个节点被赋予一个随机权重,随后通过一系列操作维护每个节点的“当前值”,并在每次操作后判断所有节点的当前值之和是否等于所有节点权重的总和(称为理想总价值)。

    核心思路:
    1.1. 初始化:

    • 使用随机数生成器为每个节点生成一个权重 nodeWeights[i]nodeWeights[i]
    • 计算所有节点权重的总和 idealTotalidealTotal
    • 处理 mm 次初始赋值操作:将节点 uu 的权重加到节点 vvcurrentValues[v]currentValues[v] 中。
    • 计算所有 currentValuescurrentValues 的总和 currentTotalcurrentTotal,并保存初始状态 initialValuesinitialValues

    2.2. 查询操作:
    程序支持四种操作类型:

    • 操作 111 u v
      从节点 vv 的当前值中减去节点 uu 的权重,同时更新 currentTotalcurrentTotal
    • 操作 222 u
      清空节点 uu 的当前值,并从 currentTotalcurrentTotal 中减去原有值。
    • 操作 333 u v
      将节点 uu 的权重加到节点 vv 的当前值,同时更新 currentTotalcurrentTotal
    • 操作 444 u
      将节点 uu 的当前值恢复到初始状态 initialValues[u]initialValues[u],并修正 currentTotalcurrentTotal

    3.3. 判定:

    • 每次操作后,检查 currentTotalcurrentTotal 是否等于 idealTotalidealTotal
    • 若相等,输出 "YES";否则输出 "NO"

    算法流程:
    1.1. 输入 n,mn,m
    2.2. 随机生成 nn 个节点权重,计算 idealTotalidealTotal
    3.3. 处理 mm 次初始赋值操作,更新 currentValuescurrentValues
    4.4. 计算 currentTotalcurrentTotal,并保存 initialValuesinitialValues
    5.5. 输入 qq 次查询,每次根据操作类型更新 currentValuescurrentValuescurrentTotalcurrentTotal
    6.6. 每次操作后输出 "YES"/"NO"

    复杂度分析:

    • 初始化:O(n+m)O(n+m)
    • 每次查询:O(1)O(1)
    • 总复杂度:O(n+m+q)O(n+m+q),适合大规模数据。

    实现细节与注意点:

    • 使用随机数生成器生成节点权重,保证每个节点权重唯一但不可预测。
    • 使用 memcpy 快速保存初始状态。
    • currentTotalcurrentTotal 始终维护所有 currentValuescurrentValues 的总和,避免每次查询重新遍历。
    • 操作 44 时要注意差值更新,避免重复累加。

    总结:
    该程序通过维护节点权重和当前值的总和,实现了对四类操作的快速模拟,并在每次操作后高效判断当前状态是否与理想状态一致。整体思路是“总和维护 ++ 状态恢复”,时间复杂度 O(1)O(1) 处理每个查询。

    #include <random>
    #include <chrono>
    #include <cstring>
    #include <iostream>
    using namespace std;
    using namespace chrono;
    
    // 最大数据规模定义
    constexpr int MAX_SIZE = 500005;
    
    // 随机数生成器(使用系统时间作为种子)
    mt19937 rng(static_cast<unsigned>(system_clock::now().time_since_epoch().count()));
    
    // 变量重命名以提高可读性
    unsigned nodeWeights[MAX_SIZE];    // 每个节点的权重值(随机生成)
    unsigned currentValues[MAX_SIZE];  // 当前各节点的累计值
    unsigned initialValues[MAX_SIZE];  // 初始状态下各节点的累计值(用于恢复操作)
    
    int main() {
        // 关闭同步以提高IO效率
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
        cout.tie(nullptr);
    
        unsigned n, m;  // n: 节点数量, m: 初始操作数量
        cin >> n >> m;
        
        // 1. 初始化节点权重并计算理想值(所有节点权重的总和)
        unsigned idealTotal = 0;
        for (unsigned i = 1; i <= n; ++i) {
            nodeWeights[i] = rng();  // 为每个节点生成随机权重
            idealTotal += nodeWeights[i];  // 累加得到理想总价值
        }
    
        // 2. 处理初始m次赋值操作
        for (unsigned i = 1; i <= m; ++i) {
            unsigned u, v;
            cin >> u >> v;
            // 将节点u的权重累加到节点v的当前值中
            currentValues[v] += nodeWeights[u];
        }
    
        // 3. 计算当前总价值并保存初始状态
        unsigned currentTotal = 0;
        for (unsigned i = 1; i <= n; ++i) {
            currentTotal += currentValues[i];  // 累加得到当前总价值
        }
        
        // 保存初始状态(从索引1开始复制n个元素)
        memcpy(initialValues + 1, currentValues + 1, n * sizeof(unsigned));
        
        // 4. 处理查询操作
        unsigned q;  // 查询次数
        cin >> q;
    
        for (unsigned i = 1; i <= q; ++i) {
            char opType;  // 操作类型
            unsigned u;   // 操作涉及的节点
            cin >> opType >> u;
    
            switch (opType) {
            case '1': {  // 从v中减去u的权重
                unsigned v;
                cin >> v;
                currentValues[v] -= nodeWeights[u];
                currentTotal -= nodeWeights[u];
                break;
            }
            case '2': {  // 清空u的当前值
                currentTotal -= currentValues[u];  // 先减去原有值
                currentValues[u] = 0;              // 再清零
                break;
            }
            case '3': {  // 向v中添加u的权重
                unsigned v;
                cin >> v;
                currentValues[v] += nodeWeights[u];
                currentTotal += nodeWeights[u];
                break;
            }
            case '4': {  // 恢复u到初始状态
                // 计算当前值与初始值的差值,并更新总价值
                currentTotal += initialValues[u] - currentValues[u];
                currentValues[u] = initialValues[u];  // 恢复值
                break;
            }
            }
    
            // 检查当前总价值是否等于理想总价值
            if (currentTotal == idealTotal) {
                cout << "YES\n";
            } else {
                cout << "NO\n";
            }
        }
    
        return 0;
    }
    
    
    • 1

    信息

    ID
    3159
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    4
    已通过
    1
    上传者