pku3468: A Simple Problem with Integers

pku3468: http://poj.org/problem?id=3468
题意:给定一段区间,其初始数值给定,Q [a,b]表示求区间[a,b]的和,C [a,b]c表示将区间[a,b]的所有数值加上c 解法:线段树lazy思想:由于整段要更新,所以每次只需更新父节点,并用lazy标记,当遇到lazy!=0时,更新下一代,同时标记,这样一直往下更新。
code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
struct abc
{
    __int64 num,lazy;
    int l,r;
}v[300009];
int w[100009];
void build(int s,int t,int n)       //建树并放入给定数值
{
    v[n].l=s;
    v[n].r=t;
    v[n].lazy=0;
    int mid=(s+t)/2;
    if(s==t)
    {
        v[n].num=w[s];
        return;
    }
    build(s,mid,n*2);
    build(mid+1,t,n*2+1);
    v[n].num=v[n*2].num+v[n*2+1].num;     //从下往上更新
}
void insert(int s,int t,int a,int n)        //插入:lazy
{
    if(v[n].l>=s&&v[n].r<=t)               //若给定范围包含n的范围,用lazy标记该点已更新
    {
        v[n].lazy+=a;
        v[n].num+=(v[n].r-v[n].l+1)*a;
        return;
    }
    if(v[n].lazy)                          //若父节点有更新,子节点也跟着更新,n的lazy=0
    {
        v[n*2].lazy+=v[n].lazy;
        v[n*2].num+=(v[n*2].r-v[n*2].l+1)*v[n].lazy;
        v[n*2+1].lazy+=v[n].lazy;
        v[n*2+1].num+=(v[n*2+1].r-v[n*2+1].l+1)*v[n].lazy;
        v[n].lazy=0;
    }
    int mid=(v[n].l+v[n].r)/2;
    if(t<=mid)
        insert(s,t,a,2*n);
    else if(s>=mid+1)
        insert(s,t,a,2*n+1);
    else
    {
        insert(s,mid,a,2*n);
        insert(mid+1,t,a,2*n+1);
    }
    v[n].num=v[n*2].num+v[n*2+1].num;          //从下往上更新父节点
}
__int64 sum(int s,int t,int n)            //求和
{
    if(v[n].l==s&&v[n].r==t)
        return v[n].num;
    if(v[n].lazy)                       //若还有未更新下代的节点,往下更新
    {
        v[n*2].lazy+=v[n].lazy;
        v[n*2].num+=(v[n*2].r-v[n*2].l+1)*v[n].lazy;
        v[n*2+1].lazy+=v[n].lazy;
        v[n*2+1].num+=(v[n*2+1].r-v[n*2+1].l+1)*v[n].lazy;
        v[n].lazy=0;
    }
    int mid=(v[n].l+v[n].r)/2;
    if(t<=mid)
        return sum(s,t,2*n);
    else if(s>mid)
        return sum(s,t,2*n+1);
    else
        return sum(s,mid,2*n)+sum(mid+1,t,2*n+1);
}
int main()
{
    int q,a,b,c,n;
    char ch;
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&w[i]);
    }
    build(1,n,1);
    getchar();
    for(int i=0;i<q;i++)
    {
        scanf("%c",&ch);
        if(ch=='Q')
        {
            scanf("%d%d",&a,&b);
            printf("%I64d\n",sum(a,b,1));
        }
        else
        {
            scanf("%d%d%d",&a,&b,&c);
            insert(a,b,c,1);
        }
        getchar();
    }
}
/*input:
10 5
1 2 3 4 5 6 7 8 9 10
Q 4 4
Q 1 10
Q 2 4
C 3 6 3
Q 2 4
output:
4
55
9
15*/

posted on 2012-07-31 11:36  acmer-jun  阅读(212)  评论(0编辑  收藏  举报

导航