线段树

一、基本概念

1.线段树是一颗二叉搜索树, 它储存的是区间的信息。

2 每个节点以结构体存储, 结构体包含以下几个信息:

区间左端点, 右端点;

3.线段树的基本思想:二分法

4:1、每个节点的左孩子区间范围为[l,mid],右孩子为[mid+1,r]

 

    2、对于结点k,左孩子结点为2*k,右孩子为2*k+1,这符合完全二叉树的性质

5.线段树可以用来查询区间的最值问题和和问题

 

#include<iostream>
#include<cstdio>
using namespace std;
struct Node {
    int l, r, w;//分别表示区间左右端点,w表示区间和
} tree[4*1000+1];
int x, y, ans;
void build(int k, int l, int r) {//建立树有值输入
    tree[k].l = l;
    tree[k].r = r;
    if (tree[k].l == tree[k].r) {
        scanf("%d", &tree[k].w);
        return ;
    }
    int mid = (l + r) / 2;
    build(k*2, l, mid);
    build (k*2+1, mid+1, r);
    tree[k].w = tree[k*2].w + tree[k*2+1].w;//求区间的和
}
/*
void build(int k, int l, int r) {//建立树无值输入
    tree[k].l = l;
    tree[k].r = r;
  tree[k].w = 0;
  if (l < r) {
      int mid = (tree[k].l + tree[k].r) >> 1;
      build(k<<1, l, mid);
      build (k<<1|1, mid+1, r);
  }
}
*/
void update(int k) {//单点更新
    if (tree[k].l == tree[k].r) {
        tree[k].w += y;
        return ;
    }
    int mid = (tree[k].l + tree[k].r)/2;
    if (x <= mid) update(k*2);
    else update(k*2+1);
    tree[k].w = tree[k*2].w + tree[k*2+1].w;//求区间的和
}
void updata1(int k, int x, int y, int w) {//区间更新
    if (tree[k].l >= x && tree[k].r <= y) {
        tree[k].w += w;
        return ;
    }
    int mid = (tree[k].l + tree[k].r) >> 1;
    if (y <= mid) updata1(k<<1, x, y, w);
    else if (x > mid) updata1(k<<1|1, x, y, w);
    else {
        updata1(k<<1, x, mid, w);
        updata1(k<<1|1, mid+1, y, w);
    }
}
void query(int k) {//区间查询
    if (tree[k].l >= x && tree[k].r <= y) {
        ans += tree[k].w;
        return ;
    }
    int mid = (tree[k].l + tree[k].r) / 2;
    if (x <= mid) query(k*2);
    if (y > mid) query(k*2+1);
}
int ask(int k, int x) {//单点查询
    if (tree[k].l == tree[k].r) {
        return tree[k].w;
    } else {
        int ans = tree[k].w;
        int mid = (tree[k].l + tree[k].r) >> 1;
        if (x <= mid) ans+=ask(k<<1, x);
        else ans+=ask(k<<1|1, x);
        return ans;
    }
}
int query1(int k) {//最值查询
    if (tree[k].l == tree[k].r) {
        return tree[k].w;
    }
    ans = 0;
    int mid = (tree[k].l + tree[k].r) / 2;
    if (x <= mid) ans = (ans,query(k*2));
    else if (y > mid) ans = (ans ,query(k*2+1));
    return ans;
}
int main() {
    int t;
    scanf("%d", &t);
    int count = 1;
    while (t--) {
        ans = 0;
        int n;
        scanf("%d", &n);
        build(1, 1, n);
        printf("Case %d:\n", count++);
        string str;
        while (cin>>str) {
            if (str == "End") break;
            scanf("%d%d", &x, &y);
            if (str == "Query") {
                int ans=query(1);
                printf("%d\n", ans);
                ans = 0;
            } else if (str == "Sub") {
                y = -y;
                update(1);
            } else {
                update(1);
            }
        }
    }
}

 

posted @ 2017-11-05 10:57  白丁一枚  阅读(125)  评论(0编辑  收藏  举报