zoukankan      html  css  js  c++  java
  • 线段树+Lazy标记(我的模版)

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 typedef unsigned long long ull;
      5 #define INF 0X3f3f3f3f
      6 const ll MAXN = 2e5 + 7;
      7 const ll MOD = 1e9 + 7;
      8 ll a[MAXN];
      9 struct node
     10 {
     11     int left, right; //区间端点
     12     ll max, sum;     //看题目要求
     13     ll lazy;
     14     void update(ll x)
     15     {
     16         sum += (right - left + 1) * x;
     17         lazy += x;
     18     }
     19 } tree[MAXN << 2];
     20 //建树,开四倍
     21 void push_up(int x)
     22 {
     23     tree[x].sum = tree[x << 1].sum + tree[x << 1 | 1].sum;
     24     tree[x].max = max(tree[x << 1].max, tree[x << 1 | 1].max);
     25 }
     26 void push_down(int x)
     27 {
     28     ll lazeval = tree[x].lazy;
     29     if (lazeval)
     30     {
     31         tree[x << 1].update(lazeval);
     32         tree[x << 1 | 1].update(lazeval);
     33         tree[x].lazy = 0;
     34     }
     35 }
     36 //若原数组从a[1]~a[n],调用build(1,1,n);
     37 void build(int x, int l, int r)
     38 {
     39     tree[x].left = l;
     40     tree[x].right = r;
     41     tree[x].sum = tree[x].lazy = 0;
     42     if (l == r) //若到达叶节点
     43     {
     44         tree[x].sum = a[l]; //存储A数组的值
     45         tree[x].max = a[l];
     46     }
     47     else
     48     {
     49         int mid = (l + r) / 2;
     50         build(x << 1, l, mid);
     51         build(x << 1 | 1, mid + 1, r);
     52         push_up(x);
     53     }
     54     return;
     55 }
     56 //update(1,l,r,v)
     57 void update(int x, int l, int r, ll v) //区间更新
     58 {
     59     int L = tree[x].left, R = tree[x].right;
     60     if (l <= L && R <= r)
     61     {
     62         tree[x].update(v);
     63         tree[x].max += v;
     64     }
     65     else
     66     {
     67         push_down(x);
     68         int mid = (L + R) / 2;
     69         if (mid >= l)
     70             update(x << 1, l, r, v);
     71         if (r > mid)
     72             update(x << 1 | 1, l, r, v);
     73         push_up(x);
     74     }
     75 }
     76 //单点更新,更新pos点,调用add(1,pos,v)
     77 void add(int x, int pos, ll v) //当前更新的节点的编号为id(一般是以1为第一个编号)。pos为需要更新的点的位置,v为修改的值的大小
     78 {
     79     
     80     int L = tree[x].left, R = tree[x].right;
     81     if (L == pos && R == pos) //左右端点均和pos相等,说明找到了pos所在的叶子节点
     82     {
     83         tree[x].sum += v;
     84         tree[x].max += v;
     85         return; //找到了叶子节点就不需要在向下寻找了
     86     }
     87     int mid = (L + R) / 2;
     88     if (pos <= mid)
     89         add(x << 1, pos, v);
     90     else
     91         add(x << 1 | 1, pos, v); //寻找k所在的子区间
     92     push_up(x);                  //向上更新
     93 }
     94 //调用query_sum(1,l,r)即可查询[l,r]区间内元素的总和
     95 //区间查询
     96 ll query_sum(int x, int l, int r)
     97 {
     98     int L = tree[x].left, R = tree[x].right;
     99     if (l <= L && R <= r)
    100         return tree[x].sum;
    101     else
    102     {
    103         push_down(x);
    104         ll ans = 0;
    105         int mid = (L + R) / 2;
    106         if (mid >= l)
    107             ans += query_sum(x << 1, l, r);
    108         if (r > mid)
    109             ans += query_sum(x << 1 | 1, l, r);
    110         push_up(x);
    111         return ans;
    112     }
    113 }
    114 //调用query_max(1,l,r)即可求[l,r]区间内元素的最大值
    115 ll query_max(int x, int l, int r)
    116 {
    117     int L = tree[x].left, R = tree[x].right;
    118     if (l == L && R == r)
    119         return tree[x].max;
    120     else
    121     {
    122         push_down(x);
    123         int mid = (L + R) / 2;
    124         if (r <= mid)
    125             return query_max(x << 1, l, r);
    126         else if (l > mid)
    127             return query_max(x << 1 | 1, l, r);
    128         else
    129             return max(query_max(x << 1, l, mid), query_max(x << 1 | 1, mid+1, r));
    130     }
    131 }
    132 int main()
    133 {
    134     ll n, m;
    135     while (scanf("%lld%lld", &n, &m) != EOF)
    136     {
    137         for (int i = 1; i <= n; i++)
    138             scanf("%lld", &a[i]);
    139         build(1, 1, n);
    140         getchar();
    141         while (m--)
    142         {
    143             int l, r;
    144             char que;
    145             scanf("%c %d %d", &que, &l, &r);
    146             getchar();
    147             if (que == 'Q')
    148                 printf("%lld
    ", query_max(1, l, r));
    149             else if (que == 'U')
    150                 update(1, l,l, r - a[l]),a[l]=r;
    151         }
    152     }
    153     return 0;
    154 }
  • 相关阅读:
    50个SQL语句(MySQL版) 问题六
    50个SQL语句(MySQL版) 问题五
    50个SQL语句(MySQL版) 问题四
    50个SQL语句(MySQL版) 问题三
    50个SQL语句(MySQL版) 问题二
    50个SQL语句(MySQL版) 问题一
    50个SQL语句(MySQL版) 建表 插入数据
    相邻元素margin的自动合并与float的坑
    STL之list
    你真的会用搜索吗?—— google 搜索技巧
  • 原文地址:https://www.cnblogs.com/graytido/p/10745106.html
Copyright © 2011-2022 走看看