poj 3466 A Simple Problem with Integers

题目链接:http://poj.org/problem?id=3468 http://poj.org/problem?id=3468 http://poj.org/problem?id=3468

思路:这是一个区间修改区间查询的题,由于题目中的给的数据比较大,那么用单个修改和查询肯定不行,所以。。。。注意数据可能比较大,应该用__int64或long long存数据。。。。。

code:

#include<stdio.h>
#include<math.h>
#define L(u) (u<<1)
#define R(u) (u<<1|1)

const int M=100010;

struct Node
{
    __int64 l,r;
    __int64 add;
    long long sum;
}node[M*4];

__int64 a[M];

void pushup(__int64 u)
{
    node[u].sum=node[L(u)].sum+node[R(u)].sum;
    return ;
}

void pushdown(__int64 u)
{
    node[L(u)].add+=node[u].add;
    node[L(u)].sum+=(node[L(u)].r-node[L(u)].l+1)*node[u].add;
    node[R(u)].add+=node[u].add;
    node[R(u)].sum+=(node[R(u)].r-node[R(u)].l+1)*node[u].add;
    node[u].add=0;
}

void build(__int64 u,__int64 left,__int64 right)
{
    node[u].l=left;
    node[u].r=right;
    node[u].add=0;
    if(left==right)
    {
        node[u].sum=a[left];
        return ;
    }
    __int64 mid=(node[u].l+node[u].r)/2;
    build(L(u),left,mid);
    build(R(u),mid+1,right);
    pushup(u);

}

void update(__int64 u,__int64 left,__int64 right,__int64 v)
{
    if(left<=node[u].l&&node[u].r<=right)
    {
        node[u].add+=v;
        node[u].sum+=(node[u].r-node[u].l+1)*v;
        return ;
    }
    //node[u].sum+=(right-left+1)*v;     //当前节点表示的区间不是查询区间的子区间
    if(node[u].add) pushdown(u);         //分析当前节点懒惰标记是否为0,不为0则要给他的子节点更新数据
    __int64 mid=(node[u].l+node[u].r)/2;
    if(right<=mid) update(L(u),left,right,v);
    else if(left>mid) update(R(u),left,right,v);
    else
    {
        update(L(u),left,mid,v);
        update(R(u),mid+1,right,v);
    }
    node[u].sum=node[L(u)].sum+node[R(u)].sum;
}

__int64 query(__int64 u,__int64 left,__int64 right)
{
     if(left<=node[u].l&&node[u].r<=right)
    {
        return node[u].sum;
    }
    if(node[u].add) pushdown(u);           <span style="font-family: Arial, Helvetica, sans-serif;">//分析当前节点懒惰标记是否为0,不为0则要给他的子节点更新数据</span>
    __int64 mid=(node[u].l+node[u].r)/2;
    if(right<=mid) return query(L(u),left,right);
    else if(left>mid) return query(R(u),left,right);
    else
    {
        return (query(L(u),left,mid)+query(R(u),mid+1,right));
    }
}

int main()
{
    __int64 n,m,i,x,y,z;
    while(scanf("%I64d%I64d",&n,&m)==2)
    {
        for(i=1;i<=n;i++)
        {
            scanf("%I64d",&a[i]);
        }
        build(1,1,n);
        char str[5];
        for(i=0;i<m;i++)
        {
            scanf("%s",str);
            if(str[0]=='C')
            {
                scanf("%I64d%I64d%I64d",&x,&y,&z);
                update(1,x,y,z);
            }
            else
            {
                scanf("%I64d%I64d",&x,&y);
                printf("%I64d\n",query(1,x,y));
            }
        }
    }
    return 0;
}

poj 3466 A Simple Problem with Integers,布布扣,bubuko.com

时间: 2024-10-24 21:24:55

poj 3466 A Simple Problem with Integers的相关文章

POJ 3468 A Simple Problem with Integers(线段树)

题目链接:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 56005   Accepted: 16903 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with

poj 3468 A Simple Problem with Integers 【线段树-成段更新】

题目:poj 3468 A Simple Problem with Integers 题意:给出n个数,两种操作 1:l -- r 上的所有值加一个值val 2:求l---r 区间上的和 分析:线段树成段更新,成段求和 树中的每个点设两个变量sum 和 num ,分别保存区间 l--r 的和 和l---r 每个值要加的值 对于更新操作:对于要更新到的区间上面的区间,直接进行操作 加上 (r - l +1)* val .下面的区间标记num += val 对于求和操作,每次进行延迟更新,把num值

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 【树状数组】

题目链接:http://poj.org/problem?id=3468 题目大意:给出一组数组v[i],有两种操作,一种给出两个数a,b,要求输出v[a]到v[b]之间的和,另一种给出三个数a,b,c,让v[a]到v[b]之间的数全都加上c. 完全是树状数组能够实现的功能,但是如果就这样单纯的套用模板,做第二种操作是更新每个值,这样的操作就有可能超时. 换一种思路,既然第二种操作是给某区间上的所有数加上相同的值,那么应该是能够简化的才对. 假设数组sum[i]为原数组从v[1]到v[i]的和,数

POJ 3468 A Simple Problem with Integers(详细题解)

这是个线段树题目,做之前必须要有些线段树基础才行不然你是很难理解的. 此题的难点就是在于你加的数要怎么加,加入你一直加到叶子节点的话,复杂度势必会很高的 具体思路 在增加时,如果要加的区间正好覆盖一个节点,则增加其节点的Inc值,不再往下走,否则要更新Sum(加上本次增量),再将增量往下传. 这样更新的复杂度就是O(log(n))在查询时,如果待查区间不是正好覆盖一个节点,就将节点的Inc往下带,然后将Inc代表的所有增量累加到Sum上后将Inc清0,接下来再往下查询. Inc往下带的过程也是区

poj 3468:A Simple Problem with Integers(线段树,区间修改求和)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 58269   Accepted: 17753 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

题目传送门 1 /* 2 线段树-成段更新:裸题,成段增减,区间求和 3 注意:开long long:) 4 */ 5 #include <cstdio> 6 #include <iostream> 7 #include <algorithm> 8 #include <cstring> 9 #include <cmath> 10 using namespace std; 11 12 #define lson l, mid, rt <<

POJ - 3468 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 numbers in a given interval. In

poj 3468 A Simple Problem with Integers (线段树 成段更新 加值 求和)

题目链接 题意: 只有这两种操作 C a b c" means adding c to each of Aa, Aa+1, ... , Ab. -10000 ≤ c ≤ 10000."Q a b" means querying the sum of Aa, Aa+1, ... , Ab. 分析:自己写的有点麻烦了,写的时候手残+脑残,改了好久. val+lazy*(r-l+1)表示和,如果lazy==0表示当前区间加的值不统一. 1 #include <iostream