zoukankan      html  css  js  c++  java
  • 线段树

    一、基本概念

    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:
    ", count++);
            string str;
            while (cin>>str) {
                if (str == "End") break;
                scanf("%d%d", &x, &y);
                if (str == "Query") {
                    int ans=query(1);
                    printf("%d
    ", ans);
                    ans = 0;
                } else if (str == "Sub") {
                    y = -y;
                    update(1);
                } else {
                    update(1);
                }
            }
        }
    }
  • 相关阅读:
    敏捷开发宣言
    OpenGL SL 优化要点
    Cocoa Touch 开发框架
    MSIL详解
    Android之Services
    Android之ActivityII
    Android之Activity
    托管执行过程
    Android之Content ProviderII
    Android之Content Providers
  • 原文地址:https://www.cnblogs.com/a863886199/p/7786848.html
Copyright © 2011-2022 走看看