POJ 3468 A Simple Problem with Integers:线段树 简单操作 注意更新到区间而非叶节点

#include<cstdio>
#include<iostream>
using namespace std;
#define Size 100000

struct Node
{
        int L, R;
        long long Sum, Inc;
        int Mid()
        {
                return (L+R)/2;
        }
}Tree[Size*3];

void CreatTree( int root, int L, int R )// 建区间树
{
        Tree[root].L = L;
        Tree[root].R = R;
        Tree[root].Sum = 0;
        Tree[root].Inc = 0;

        if( L==R )
            return;

        CreatTree( root*2+1, L, (L+R)/2 );
        CreatTree( root*2+2, (L+R)/2+1, R );
}

void Insert( int root, int i, int  j )// 位置i 插入 j
{
        if( Tree[root].L == Tree[root].R )
        {
                Tree[root].Sum = j;
                return ;
        }

        Tree[root].Sum+=j;

        if( i<=Tree[root].Mid() )
            Insert( root*2+1, i, j );
        else
            Insert( root*2+2, i, j );

}

void Add( int  root, int s, int e, int j )// 区间[s, e] 上每个元素加j
{
        if( Tree[root].L==s && Tree[root].R==e )
        {
                Tree[root].Inc += j;
                return ;
        }

        Tree[root].Sum+=(e-s+1)*j;

        if( s>Tree[root].Mid() )
            Add( root*2+2, s, e, j );
        else
            if( e<=Tree[root].Mid() )
            Add( root*2+1, s, e, j );
        else
        {
            Add( root*2+1, s, Tree[root].Mid(), j );
            Add( root*2+2, Tree[root].Mid()+1, e, j );
        }
}

long long Query( int root, int s, int e )// 查询 区间[s,e]的和
{
        if( Tree[root].L==s && Tree[root].R==e )
                return Tree[root].Sum+Tree[root].Inc*(e-s+1);

        Tree[root].Sum+=(Tree[root].R-Tree[root].L+1)*Tree[root].Inc;
        Add( 2*root+1, Tree[root].L, Tree[root].Mid(), Tree[root].Inc );
        Add( 2*root+2, Tree[root].Mid()+1, Tree[root].R, Tree[root].Inc );
        Tree[root].Inc = 0;

        if( e<=Tree[root].Mid() )
                return Query( root*2+1, s, e );
        else
            if( s>Tree[root].Mid() )
                return Query( root*2+2, s, e );
        else
                return Query( root*2+1, s, Tree[root].Mid() ) +
                              Query( root*2+2, Tree[root].Mid()+1, e );
}

int main()
{
        int N, Q, a, b, c;
        char Cmd;
        scanf( "%d%d", &N, &Q );
        CreatTree( 0, 1, N );
        for( int i=1; i<=N; i++ )
        {
                scanf( "%d", &a );
                Insert( 0, i, a );
        }
        for( int i=0; i<Q; i++ )
        {
                cin>>Cmd;
                if( Cmd == ‘Q‘ )
                {
                        scanf( "%d%d", &a, &b );
                        printf( "%I64d\n", Query( 0, a, b ) );
                }
                else
                {
                        scanf( "%d%d%d", &a, &b, &c );
                        Add( 0, a, b, c );
                }
        }
        return 0;
}

代码虽然长了点但都是线段树的基本操作,所以整体思路还是清晰的,还有一个版本是 节点带有左右子节点指针的,省空间那种,容易错比赛时候最好还是避免,平时当练习也不错,现在我就去用带指针的做一遍。

时间: 2024-08-09 19:53:31

POJ 3468 A Simple Problem with Integers:线段树 简单操作 注意更新到区间而非叶节点的相关文章

POJ 3468 A Simple Problem with Integers //线段树的成段更新

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 59046   Accepted: 17974 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

POJ 3468 A Simple Problem with Integers(线段树区间更新)

题目地址:POJ 3468 打了个篮球回来果然神经有点冲动..无脑的狂交了8次WA..居然是更新的时候把r-l写成了l-r... 这题就是区间更新裸题.区间更新就是加一个lazy标记,延迟标记,只有向下查询的时候才将lazy标记向下更新.其他的均按线段树的来就行. 代码如下: #include <iostream> #include <cstdio> #include <cstring> #include <math.h> #include <stac

poj 3468 A Simple Problem with Integers 线段树第一次 + 讲解

A Simple Problem with Integers Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of

POJ 3468 A Simple Problem with Integers (线段树区域更新)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 62431   Accepted: 19141 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

[POJ] 3468 A Simple Problem with Integers [线段树区间更新求和]

A Simple Problem with Integers Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of

poj 3468 A Simple Problem with Integers 线段树加延迟标记

A Simple Problem with Integers Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of

POJ 3468 A Simple Problem with Integers(线段树区间更新区间求和)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 67511   Accepted: 20818 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

poj 3468 A Simple Problem with Integers 线段树区间更新

点击打开链接题目链接 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 63565   Accepted: 19546 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations.

POJ 3468 A Simple Problem with Integers 线段树 区间更新 区间查询

题目链接: http://poj.org/problem?id=3468 题目描述: 一组数列, 可进行一段区间加上某一个数, 和区间查询 解题思路: 线段树, 之前的那道题是求总区间直接输出sum[1] 就可以了, 这次有了区间查询, 同理, 查询的时候Pushdown 代码: #include <iostream> #include <cstdio> #include <string> #include <vector> #include <map