线段树基础模板c++

在这里插入图片描述

在这里插入图片描述

线段树的基础模板代码

#include <bits/stdc++.h>
using namespace std;
#define N 100005
#define int long long

#define lc p << 1     // 2*i
#define rc p << 1 | 1 // 2*i+1

int n, m;
int w[N];

struct node
{
   

  int l, r, sum, add;

} tr[N * 4];
// 构建线段树

void pushup(int p)
{
   
  tr[p].sum = tr[lc].sum + tr[rc].sum;
}
void pushdown(int p)
{
   
  if (tr[p].add)

  {
   
    tr[lc].sum += tr[p].add * (tr[lc].r - tr[lc].l + 1),
        tr[rc].sum += tr[p].add * (tr[rc].r - tr[rc].l + 1),
        tr[lc].add += tr[p].add,
        tr[rc].add += tr[p].add,
        tr[p].add = 0;
  }
}
void build(int p, int l, int r)
{
   
  tr[p] = {
   l, r, w[l], 0};
  if (l == r)
    return;
  int mid = l + r >> 1;
  build(lc, l, mid);
  build(rc, mid + 1, r);
  pushup(p);
}
int query(int p, int x, int y)
{
    // 区查
  if (x <= tr[p].l && tr[p].r <= y)
    return tr[p].sum;
  int m = tr[p].l + tr[p].r >> 1;
  pushdown(p);
  int sum = 0;
  if (x <= m)
    sum += query(lc, x, y);
  //
  if (y > m)
    sum += query(rc, x, y);
  return sum;
}

void update(int p, int x, int y, int k)
{
   
  // 修改区间的值'
  if (x <= tr[p].l && tr[p].r <= y)
  {
   
    tr[p].sum += (tr[p].r - tr[p].l + 1) * k;
    tr[p].add += k;
    return;
  }
  int mid = tr[p].l + tr[p].r >> 1;
  pushdown(p); // 先下沉
  if (x <= mid)
  {
   
    update(lc, x, y, k);
  }
  if (y > mid)
  {
   
    update(rc, x, y, k);
  }
  pushup(p); // 再上乘
}

// 区间修改 对于区间[4,9] 内的每个数字
signed main()
{
   
  cin >> n >> m;

  for (int i = 1; i <= n; i++)
  {
   
    int x;
    cin >> x;
    w[i] = x;
  }
  build(1, 1, n);
  for (int i = 1; i <= m; i++)
  {
   
    int a, x, y, k;
    cin >> a >> x >> y;
    if (a == 1)
    {
   
      cin >> k;
      update(1, x, y, k);
    }
    else if (a == 2)
    {
   

      cout << query(1, x, y) << endl;
    }
  }
}

在这里插入图片描述

对点进行修改,从跟节点进入,找到根节点,将根节点的值修改下

在这里插入图片描述

查询区间
在这里插入图片描述

区间修改如果直接修改容易看出来时间复杂度是on的

懒惰修改在这里插入图片描述

修改上面区间的sum值,

https://ac.nowcoder.com/acm/contest/63746/A
题目,采用线段树的代码来解决问题

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define N 200005
#define lc p << 1
#define rc p << 1 | 1

int n, m;
struct node
{
   
  int l, r, sum, add;

} tr[N * 4];
int w[N];

void pushup(int p)
{
   
  tr[p].sum = tr[lc].sum + tr[rc].sum;
}
void pushdown(int p)
{
   
  if (tr[p].add)
    //^异或运算 
  {
   
    tr[lc].add ^= tr[p].add; //
    tr[rc].add ^= tr[p].add;

    tr[lc].sum = tr[lc].r - tr[lc].l + 1 - tr[lc].sum;
    tr[rc].sum = tr[rc].r - tr[rc].l + 1 - tr[rc].sum;
    tr[p].add = 0;
  }
}
void build(int p, int l, int r)
{
   
  tr[p] = {
   l, r};
  if (l == r)
  {
   
    tr[p].sum = w[l];
    return;
  }

  int mid = l + r >> 1;
  build(lc, l, mid);
  build(rc, mid + 1, r);
  pushup(p);
}

int query(int p, int x, int y)
{
    // 区查
  // 如果以及完全覆盖掉
  if (x <= tr[p].l && tr[p].r <= y)
    return tr[p].sum;
  int m = tr[p].l + tr[p].r >> 1; // 没有完全覆盖就裂开
  pushdown(p);

  int sum = 0; // 定义局部变量 递归进入
  if (x <= m)
    sum += query(lc, x, y);
  //
  if (y > m)
    sum += query(rc, x, y);
  return sum;
}
// 查询时不变的 修改会发生变化

void update(int p, int x, int y)
{
   
  // 修改区间的值'
  if (x <= tr[p].l && tr[p].r <= y)
  {
   
    // 如果符合了
    // 区间修改
    tr[p].add ^= 1;//和1进行异或取反
    tr[p].sum = tr[p].r - tr[p].l + 1 - tr[p].sum;
    return;
  }

  int mid = tr[p].l + tr[p].r >> 1;
  pushdown(p); // 先下沉
  if (x <= mid)
  {
   
    update(lc, x, y);
  }
  if (y > mid)
  {
   
    update(rc, x, y);
  }
  pushup(p); // 再上乘
}

signed main()
{
   
  cin >> n >> m;
  string s;
  cin >> s;
  for (int i = 0; i < s.length(); i++)
  {
   
    w[i + 1] = s[i] - '0';
  }

  build(1, 1, n);

  for (int i = 1; i <= m; i++)
  {
   
    int a, x, y;
    cin >> a >> x >> y;
    if (a == 0)
    {
   

      update(1, x, y);
    }
    else if (a == 1)
    {
   

      cout << query(1, x, y) << endl;
    }
  }
}

相关推荐

  1. C++】线段(一)

    2023-12-07 04:06:02       37 阅读
  2. 线段、树状数组、归并排序模板

    2023-12-07 04:06:02       14 阅读
  3. 决斗(线段

    2023-12-07 04:06:02       28 阅读
  4. 风信子(线段

    2023-12-07 04:06:02       33 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-07 04:06:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-07 04:06:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-07 04:06:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-07 04:06:02       18 阅读

热门阅读

  1. centos用户相关命令

    2023-12-07 04:06:02       30 阅读
  2. springboot工作原理

    2023-12-07 04:06:02       30 阅读
  3. 联合体union

    2023-12-07 04:06:02       36 阅读
  4. Oracle官网 账号及密码 -- 笔记

    2023-12-07 04:06:02       39 阅读
  5. 将元胞添加到元胞数组

    2023-12-07 04:06:02       34 阅读
  6. PTA 6-143 密码转换

    2023-12-07 04:06:02       38 阅读
  7. 2023亚太地区五岳杯量子计算挑战赛

    2023-12-07 04:06:02       41 阅读
  8. 前端面试题【构建工具篇】

    2023-12-07 04:06:02       29 阅读
  9. ROS 欧拉角

    2023-12-07 04:06:02       35 阅读
  10. FAQ:Constructors篇

    2023-12-07 04:06:02       28 阅读
  11. HG/T 5367.2-2022 轨道交通车辆耐电弧绝缘涂料检测

    2023-12-07 04:06:02       28 阅读
  12. rocketMQ-发送消息

    2023-12-07 04:06:02       30 阅读
  13. 获取图像大小 - 编程指南

    2023-12-07 04:06:02       38 阅读
  14. MongoDB导入导出命令

    2023-12-07 04:06:02       31 阅读