线段树

基本线段树

你能回答这些问题吗

线段树

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 5e5+5;

int n, m;

struct Node{
    int l, r;
    int tsum;
    int lsum, rsum;
    int sum;
}tree[N*4];

void pushup(Node &node, Node &lnode, Node &rnode)
{
    node.sum = lnode.sum + rnode.sum;
    node.lsum = max(lnode.lsum, lnode.sum + rnode.lsum);
    node.rsum = max(rnode.rsum, rnode.sum + lnode.rsum);
    node.tsum = max(max(lnode.tsum, rnode.tsum), lnode.rsum + rnode.lsum);
}

void pushup(int u)
{
    pushup(tree[u], tree[u<<1], tree[u<<1|1]);
}

void build(int u, int l, int r)
{
    tree[u] = {l, r, 0, 0, 0, 0};
    if(l == r)
    {
        return;
    }
    int mid = l+r>>1;
    build(u<<1, l, mid);
    build(u<<1|1, mid+1, r);
    pushup(u);
}

//将第x个数改为v
void modify(int u, int x, int v)
{
    if(tree[u].l == tree[u].r)
    {
        tree[u] = {tree[u].l, tree[u].r, v, v, v, v}; //lsum, rsum必须有元素
        return;
    }
    int mid = tree[u].l + tree[u].r >> 1;
    if(x <= mid)
    {
        modify(u<<1, x, v);
    }
    else
    {
        modify(u<<1|1, x, v);
    }
    pushup(u);
}

//查询区间L~R的最大连续子段和
Node query(int u, int L, int R)
{
    if(tree[u].l >= L && tree[u].r <= R)
    {
        return tree[u];
    }
    int mid = tree[u].l + tree[u].r >> 1;
    Node ltree, rtree;
    bool haveL = false, haveR = false;
    if(mid >= L) //包含左子树
    {
        ltree = query(u<<1, L, R);
        haveL = true;
    }
    if(mid+1 <= R) //包含右子树
    {
        rtree = query(u<<1|1, L, R);
        haveR = true;
    }
    if(haveL && haveR)
    {
        Node ans;
        pushup(ans, ltree, rtree);
        return ans;
    }
    else if(haveL)
    {
        return ltree;
    }
    else if(haveR)
    {
        return rtree;
    }

}

int main()
{
    cin >> n >> m;
    build(1, 1, n);
    for(int i = 1; i <= n; ++ i)
    {
        int tp;
        scanf("%d", &tp);
        modify(1, i, tp);
    }
    while(m --)
    {
        int k, x, y;
        scanf("%d%d%d", &k, &x, &y);
        if(k == 1)
        {
            if(x > y)   swap(x, y);
            Node ans = query(1, x, y);
            printf("%d\n", ans.tsum);
        }
        else
        {
            modify(1, x, y);
        }
    }
    return 0;
}
上一篇:查找单链表倒数第k个位置上的结点(高效算法)


下一篇:头插法建立链表