poj 3468(简单线段树区间更新)

A Simple Problem with Integers

Time Limit: 5000MS   Memory Limit: 131072K
Total Submissions: 61936   Accepted: 18934
Case Time Limit: 2000MS

Description

You have N integers, A1A2, ... , 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.

Input

The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000.

The second line contains N numbers, the initial values of A1A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000.

Each of the next Q lines represents an operation.

"C a b c" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.

"Q a b" means querying the sum of AaAa+1, ... , Ab.

Output

You need to answer all Q commands in order. One answer in a line.

Sample 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

Sample Output

4
55
9
15

Hint

The sums may exceed the range of 32-bit integers.

Source

POJ Monthly--2007.11.25, Yang Yi

#include<iostream>
#include<algorithm>
#include<stdio.h>
using namespace std;
int n,q;
#define ll long long
struct Node{
    int left,right;
    ll sum,p;        //p表示left 到 right 的增量
}a[400010];
void built(int cur,int x,int y){
    a[cur].left=x;
    a[cur].right=y;
    a[cur].p=0;
    if(x==y){
        scanf("%I64d",&a[cur].sum);
        return ;
    }
    int mid=(x+y)>>1;
    built(cur<<1,x,mid);
    built(cur<<1|1,mid+1,y);
    a[cur].sum=a[cur<<1].sum+a[cur<<1|1].sum;
}
void update(int cur,int x,int y,ll val){
    if(a[cur].left==x && a[cur].right==y){
        a[cur].sum+=val*(y-x+1);
        a[cur].p+=val;
        return ;
    }
    if(a[cur].p){
        a[cur<<1].p+=a[cur].p;
        a[cur<<1|1].p+=a[cur].p;
        a[cur<<1].sum+=a[cur].p*(a[cur<<1].right-a[cur<<1].left+1);
        a[cur<<1|1].sum+=a[cur].p*(a[cur<<1|1].right-a[cur<<1|1].left+1);
        a[cur].p=0;
    }
    int mid=(a[cur].left+a[cur].right)>>1;
    if(y<=mid)
        update(cur<<1,x,y,val);
    else if(x>mid)
        update(cur<<1|1,x,y,val);
    else{
        update(cur<<1,x,mid,val);
        update(cur<<1|1,mid+1,y,val);
    }
    a[cur].sum=a[cur<<1].sum+a[cur<<1|1].sum;
}

ll query(int cur,int x,int y){
    if(a[cur].left==x && a[cur].right==y){
        return a[cur].sum;
    }
    if(a[cur].p){
        a[cur<<1].p+=a[cur].p;
        a[cur<<1|1].p+=a[cur].p;
        a[cur<<1].sum+=a[cur].p*(a[cur<<1].right-a[cur<<1].left+1);
        a[cur<<1|1].sum+=a[cur].p*(a[cur<<1|1].right-a[cur<<1|1].left+1);
        a[cur].p=0;
    }
    int mid=(a[cur].left+a[cur].right)>>1;
    if(y<=mid)
        return query(cur<<1,x,y);
    else if(x>mid)
        return query(cur<<1|1,x,y);
    else{
        return query(cur<<1,x,mid)+query(cur<<1|1,mid+1,y);
    }
}
int main(){
    while(scanf("%d%d",&n,&q)!=EOF){
        built(1,1,n);
        while(q--){
            char s[2]; scanf("%s",s);

            if(s[0]=='C'){
                int x,y;
                ll val;
                scanf("%d%d%I64d",&x,&y,&val);
                update(1,x,y,val);
            }
            else{
                int x,y;
                scanf("%d%d",&x,&y);
                printf("%I64d\n",query(1,x,y));
            }
        }
    }
    return 0;
}

poj 3468(简单线段树区间更新)

时间: 2024-08-27 04:03:00

poj 3468(简单线段树区间更新)的相关文章

POJ 4047 Garden 线段树 区间更新

给出一个n个元素的序列,序列有正数也有负数 支持3个操作: p x y 0.p=0时,把第x个的值改为y 1.p=1时,交换第x个和第y个的值 2.p=2时,问区间[x,y]里面连续k个的子序列的最大和(保证y-x+1>=k) 我们只要定义数组v v[i]表示原序列中,从第i个开始,连续k个元素的值的和 然后我们只需要维护一棵线段树,树的叶子节点表示数组v 树的节点维护: 区间[l,r]中,连续k个的子序列的最大和,即数组v的最大值 这样的话,3个操作就变为: 0.把区间[max(x-k+1,0

(简单) 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. 题意

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 Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 59798   Accepted: 18237 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: 70442   Accepted: 21723 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(线段树 区间更新)

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 2528 Mayor&#39;s posters (线段树区间更新+离散化)

题目链接:http://poj.org/problem?id=2528 给你n块木板,每块木板有起始和终点,按顺序放置,问最终能看到几块木板. 很明显的线段树区间更新问题,每次放置木板就更新区间里的值.由于l和r范围比较大,内存就不够了,所以就用离散化的技巧 比如将1 4化为1 2,范围缩小,但是不影响答案. 写了这题之后对区间更新的理解有点加深了,重点在覆盖的理解(更新左右两个孩子节点,然后值清空),还是要多做做题目. 1 #include <iostream> 2 #include <

POJ 2777 Count Color (线段树区间更新加查询)

Description Chosen Problem Solving and Program design as an optional course, you are required to solve all kinds of problems. Here, we get a new problem. There is a very long board with length L centimeter, L is a positive integer, so we can evenly d

线段树区间更新+向量知识——POJ 2991

对应POJ题目:点击打开链接 Crane Time Limit: 2000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u Submit Status Description ACM has bought a new crane (crane -- je?áb) . The crane consists of n segments of various lengths, connected by flexible joints