线段树

原创 2015年07月10日 21:33:28

线段树模板啦
维护区间和,最大值,最小值
资瓷区间加值,区间赋值

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

const int INF = 0x3f3f3f3f;
const int maxn = 105;

int a[maxn];
int add[maxn << 2], col[maxn << 2];
int minv[maxn << 2], maxv[maxn << 2], sum[maxn << 2];

void maintain(int o, int L, int R)
{
    if(L >= R) return ;
    int lc = o << 1, rc = o << 1 | 1;
    sum[o] = sum[lc] + sum[rc];
    maxv[o] = max(maxv[lc], maxv[rc]);
    minv[o] = min(minv[lc], minv[rc]);
}

void pushdown(int o, int L, int R)
{
    if(L >= R) return ;
    int M = (L + R) >> 1, lc = o << 1, rc = o << 1 | 1;
    if(col[o])
    {
        col[lc] = col[rc] = col[o];
        add[lc] = add[rc] = 0;
        sum[lc] = col[o] * (M-L+1);
        sum[rc] = col[o] * (R-M);
        maxv[lc] = maxv[rc] = minv[lc] = minv[rc] = col[o];
        col[o] = 0;
    }
    if(add[o])
    {
        add[lc] += add[o]; add[rc] += add[o];
        sum[lc] += add[o] * (M-L+1); sum[rc] += add[o] * (R-M);
        maxv[lc] += add[o]; maxv[rc] += add[o];
        minv[lc] += add[o]; minv[rc] += add[o];
        add[o] = 0;
    }
}

int op, qv, _sum, _max, _min;

void update(int o, int L, int R, int ql, int qr)
{
    if(L == ql && qr == R)
    {
        if(op == 1)//add
        {
            add[o] += qv;
            maxv[o] += qv;
            minv[o] += qv;
            sum[o] += qv * (R-L+1);
        }
        else//set
        {
            col[o] = maxv[o] = minv[o] = qv;
            add[o] = 0;
            sum[o] = qv * (R-L+1);
        }
    }
    else
    {
        pushdown(o, L, R);
        int M = (L + R) >> 1;
        if(qr <= M) update(o << 1, L, M, ql, qr);
        else if(M < ql) update(o << 1 | 1, M+1, R, ql, qr);
        else
        {
            update(o << 1, L, M, ql, M);
            update(o << 1 | 1, M+1, R, M+1, qr);
        }
        maintain(o, L, R);
    }
}

void query(int o, int L, int R, int ql, int qr)
{
    if(L == ql && qr == R)
    {
        _sum += sum[o];
        _max = max(_max, maxv[o]);
        _min = min(_min, minv[o]);
    }
    else
    {
        pushdown(o, L, R);
        int M = (L + R) >> 1;
        if(qr <= M) query(o << 1, L, M, ql, qr);
        else if(M < ql) query(o << 1 | 1, M+1, R, ql, qr);
        else
        {
            query(o << 1, L, M, ql, M);
            query(o << 1 | 1, M+1, R, M+1, qr);
        }
        maintain(o, L, R);
    }
}

void build(int o, int L, int R)
{
    if(L == R) maxv[o] = minv[o] = sum[o] = a[L];
    else
    {
        int M = (L + R) >> 1;
        build(o << 1, L, M);
        build(o << 1 | 1, M+1, R);
        maintain(o, L, R);
    }
}

int main()
{
    freopen("input.txt","r",stdin);
    freopen("out2.txt","w",stdout);

    int n, q;
    scanf("%d%d", &n, &q);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    build(1, 1, n);
    while(q--)
    {
        int ql, qr;
        scanf("%d", &op);
        if(op <= 2)
        {
            scanf("%d%d%d", &ql, &qr, &qv);
            update(1, 1, n, ql, qr);
        }
        else
        {
            scanf("%d%d", &ql, &qr);
            _sum = _max = 0; _min = INF;
            query(1, 1, n, ql, qr);
            printf("%d %d %d\n", _min, _max, _sum);
        }
    }

    fclose(stdin);
    fclose(stdout);
    return 0;
}

线段树详解(单点更新与成段更新\区间更新操作)

本文纯属原创,转载请注明出处,谢谢。 距离第一次接触线段树已经一年多了,再次参加ACM暑假集训,这一次轮到我们这些老家伙们给学弟学妹们讲解线段树了,所以就自己重新把自己做过的题目看了一遍,然后写篇博客...
  • u014705673
  • u014705673
  • 2015年07月06日 15:57
  • 6208

线段树之建树,单点更新以及区间查询

线段树之建树,单点更新以及区间查询       线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。      使用线段树可以快速的查找某一个节...
  • ruangongshi
  • ruangongshi
  • 2015年08月09日 11:07
  • 1557

[线段树]深入理解:线段树的构建和分解方法

如果还不了解基本的线段树,请点击这里查看。 ——线段树的构造,实际上是利用了二分的方法。每次在构造相应区间时,需要按照二分的规则来继续分解,并构造区间内的子区间,存成一个新的节点,并以此保留...
  • u012848631
  • u012848631
  • 2015年07月16日 08:28
  • 1177

线段树应用示例程序

  • 2017年05月18日 14:52
  • 2.39MB
  • 下载

ZKW线段树源码-pascal

  • 2015年03月10日 19:21
  • 104KB
  • 下载

线段树入门

  • 2015年05月03日 11:01
  • 204KB
  • 下载

线段树学习资料

  • 2013年09月25日 23:04
  • 161KB
  • 下载

线段树资料

  • 2014年02月18日 22:52
  • 990KB
  • 下载

hdu acm1166线段树

  • 2014年05月03日 18:41
  • 2KB
  • 下载

线段树(一)

  • 2012年10月18日 07:54
  • 1KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:线段树
举报原因:
原因补充:

(最多只允许输入30个字)