线段树(区间更新)


#include 
#include 
using namespace std;

typedef long long ll;

ll a[100005];
struct node 
{
  int l, r;
  ll  sum, lazy;
}tree[500005];
int n;

void Updown(int rt)              //更新区间的值
{
  tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum;
}

void Pushdown(int rt)
{
  if(tree[rt].lazy)
  {
    tree[rt << 1].lazy += tree[rt].lazy;
    tree[rt << 1 | 1].lazy += tree[rt].lazy;
    tree[rt << 1].sum += tree[rt].lazy * (tree[rt << 1].r - tree[rt].l + 1);
    tree[rt << 1 | 1].sum += tree[rt].lazy * (tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1);
    tree[rt].lazy = 0;
  }
}

void Build(int l, int r, int rt)       ///建线段树
{
  tree[rt].l = l;
  tree[rt].r = r;
  tree[rt].sum = 0;
  tree[rt].lazy = 0;
  if(l == r)
  {
    tree[rt].sum = a[l];
    return;
  }
  int mid = (l + r) / 2;
  Build(l, mid, rt << 1);
  Build(mid + 1, r, rt << 1 | 1);
  Updown(rt);
} 

ll Query(int l, int r, int rt)         ///询问区间的值
{
  if(tree[rt].l == l && tree[rt].r == r)
  {
    return tree[rt].sum;
  }
  Pushdown(rt);
  int mid = (tree[rt].l + tree[rt].r) / 2;
  ll ans = 0;
  if(mid >= r)
   ans += Query(l, r, rt << 1);
  else if(mid < l)
    ans += Query(l, r, rt << 1 | 1);
  else 
  {
    ans += Query(l, mid, rt << 1);
    ans += Query(mid + 1, r, rt << 1 | 1);
  }
  return ans;
}

void Update(int l, int r, int val, int rt)
{
  if(tree[rt].l == l && tree[rt].r == r)
  {
     tree[rt].lazy += val;
     tree[rt].sum += val * (tree[rt].r - tree[rt].l + 1);
     return;
  }
  Pushdown(rt);
  int mid = (tree[rt].r + tree[rt].l) / 2;
  if(mid >= r)
    Update(l, r, val, rt << 1);
  else if(mid < l)
    Update(l, r, val, rt << 1 | 1);
  else 
  {
    Update(l, mid, val, rt << 1);
    Update(mid + 1, r, val, rt << 1 | 1);
  }
  Updown(rt);
}



你可能感兴趣的:(线段树)