2569. 更新数组后处理求和查询(模板 + 普通线段树熟练掌握)

简介: 2569. 更新数组后处理求和查询(模板 + 普通线段树熟练掌握)

题目

思路

  • 操作2和操作3都非常好实现,直接累加一个和就行
  • 关键在于操作1(nums1数组所有元素大小在0~1之间)翻转
  • 线段树相比树状数组更好理解
  • 具体细节见代码

代码

ini

复制代码

class Solution {
typedef long long LL;
static const int N = 100010;
int n, m;
int w[N];
struct Node
{
    int l, r;
    LL sum, add;//懒标记:是否翻转过
}tr[N * 4];
void pushup(int u)
{
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}
void pushdown(int u)
{
    auto &root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1];
    if (root.add)
    {
        left.add ^= root.add;
        left.sum = (LL)(left.r - left.l + 1 - left.sum);
        right.add ^= root.add;
        right.sum = (LL)(right.r - right.l + 1 - right.sum);
        root.add = 0;
    }
}
void build(int u, int l, int r)
{
    if (l == r) tr[u] = {l, r, w[r], 0};
    else
    {
        tr[u] = {l, r};
        int mid = l + r >> 1;
        build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }
}
void modify(int u, int l, int r, int d)
{
    if (tr[u].l >= l && tr[u].r <= r)
    {
        tr[u].add ^= d;
        tr[u].sum = (LL)(tr[u].r - tr[u].l + 1 - tr[u].sum);
        
    }
    else    // 一定要分裂
    {
        pushdown(u);
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid) modify(u << 1, l, r, d);
        if (r > mid) modify(u << 1 | 1, l, r, d);
        pushup(u);
    }
}
LL query(int u, int l, int r)
{
    if (tr[u].l >= l && tr[u].r <= r) return tr[u].sum;
    pushdown(u);
    int mid = tr[u].l + tr[u].r >> 1;
    LL sum = 0;
    if (l <= mid) sum = query(u << 1, l, r);
    if (r > mid) sum += query(u << 1 | 1, l, r);
    return sum;
}
public:
    vector<long long> handleQuery(vector<int>& nums1, vector<int>& nums2, vector<vector<int>>& queries) {
        int n = nums1.size();
        LL add = 0;
        for(auto &x:nums2)add += x;
        for(int i = 1;i <= n;i ++)
        {
            w[i] = nums1[i-1];
        }
        build(1,1,n);
        
        vector<LL> ans;
        for(auto &t:queries)
        {
            if(t[0] == 1)modify(1,t[1]+1,t[2]+1,1);
            else if(t[0] == 2)add += tr[1].sum*t[1];
            else ans.push_back(add);
        }
        return ans;
    }
};


相关文章
|
算法 测试技术 C#
C++算法前缀和的应用:分割数组的最大值的原理、源码及测试用例
C++算法前缀和的应用:分割数组的最大值的原理、源码及测试用例
|
6月前
|
搜索推荐 算法 Python
如何实现归并排序算法? 要求:编写一个Python函数,输入一个无序列表,返回排序后的列表。
如何实现归并排序算法? 要求:编写一个Python函数,输入一个无序列表,返回排序后的列表。
52 2
|
5月前
|
算法 搜索推荐
数据结构和算法——表排序(算法概述、物理排序、复杂度分析,包含详细清晰图示过程)
数据结构和算法——表排序(算法概述、物理排序、复杂度分析,包含详细清晰图示过程)
41 0
|
6月前
【每日一题Day277】LC2569更新数组后处理求和查询 | 线段树
【每日一题Day277】LC2569更新数组后处理求和查询 | 线段树
29 0
|
11月前
|
算法 测试技术 C#
C++前缀和算法的应用:分割数组的最多方案数 原理源码测试用例
C++前缀和算法的应用:分割数组的最多方案数 原理源码测试用例
|
算法 Java 网络架构
代码随想录训练营day27| 39. 组合总和 40.组合总和II 131.分割回文串
代码随想录训练营day27| 39. 组合总和 40.组合总和II 131.分割回文串
|
算法
组合排序回溯编程题集合(leetcode)
组合排序回溯编程题集合(leetcode)
|
SQL 移动开发 BI
【SQL开发实战技巧】系列(二十三):数仓报表场景☞ 如何对数据排列组合去重以及通过如何找到包含最大值和最小值的记录这个问题再次用执行计划给你证明分析函数性能不一定高
怎样对数据组合重新排列并去重的问题、通过如何找到包含最大值和最小值的记录这个问题再次用执行计划给你证明分析函数性能不一定高【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。本篇文章主要介绍的两个方面,第一个方面曾经有好几个网友和同事问我,第二个问题真的是很多同行的通病,认为分析函数是万金油,一股脑用。
【SQL开发实战技巧】系列(二十三):数仓报表场景☞ 如何对数据排列组合去重以及通过如何找到包含最大值和最小值的记录这个问题再次用执行计划给你证明分析函数性能不一定高