(线段树成段更新+区间求和) poj 3468

D - A Simple Problem with Integers

Time Limit:5000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u

Submit Status Practice POJ 3468

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 abc" means adding c to each of AaAa+1, ... , Ab. -10000 ≤ c ≤ 10000.
"Q ab" 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
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define N 100010
#define LL long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
LL add[N<<2],sum[N<<2];
int n,m;
void pushup(int rt)
{
      sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt)
{
      add[rt]=0;
      if(l==r)
      {
            scanf("%I64d",&sum[rt]);
            return ;
      }
      int m=(l+r)>>1;
      build(lson);
      build(rson);
      pushup(rt);
}
void pushdown(int rt,int m)
{
      if(add[rt])
      {
         add[rt<<1]+=add[rt];
         add[rt<<1|1]+=add[rt];
         sum[rt<<1]+=(m-(m>>1))*add[rt];
         sum[rt<<1|1]+=(m>>1)*add[rt];
         add[rt]=0;
      }
}
void update(int L,int R,int c,int l,int r,int rt)
{
      if(L<=l&&r<=R)
      {
           add[rt]+=c;
           sum[rt]+=(LL)(r-l+1)*c;
           return ;
      }
      pushdown(rt,r-l+1);
      int m=(l+r)>>1;
      if(L<=m) update(L,R,c,lson);
      if(m<R) update(L,R,c,rson);
      pushup(rt);
}
LL query(int L,int R,int l,int r,int rt)
{
      if(L<=l&&r<=R)
      {
            return sum[rt];
      }
      pushdown(rt,r-l+1);
      int m=(l+r)>>1;
      LL ret=0;
      if(L<=m) ret+=query(L,R,lson);
      if(m<R) ret+=query(L,R,rson);
      return ret;
}
int main()
{
     scanf("%d%d",&n,&m);
     build(1,n,1);
     while(m--)
     {
           int a,b,c;
           char s[5];
           scanf("%s",s);
           if(s[0]==‘Q‘)
           {
               scanf("%d%d",&a,&b);
               printf("%I64d\n",query(a,b,1,n,1));
           }
           else
           {
                 scanf("%d%d%d",&a,&b,&c);
                 update(a,b,c,1,n,1);
           }
     }
     return 0;
}

  

时间: 2024-11-10 11:28:58

(线段树成段更新+区间求和) poj 3468的相关文章

POJ训练计划2777_Count Color(线段树/成段更新/区间染色)

解题报告 题意: 对线段染色,询问线段区间的颜色种数. 思路: 本来直接在线段树上染色,lz标记颜色.每次查询的话访问线段树,求出颜色种数.结果超时了,最坏的情况下,染色可以染到叶子节点. 换成存下区间的颜色种数,这样每次查询就不用找到叶子节点了,用按位或来处理颜色种数. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace

HDU 3397 Sequence operation(线段树&#183;成段更新&#183;区间合并&#183;混合操作)

题意  给你一个只有0, 1的数组  有这些操作 0. 将[a, b]区间的所有数都改为0 1. 将[a, b]区间的所有数都改为1 2. 将[a, b]区间的所有数都取反 即与1异或 3. 输出区间[a, b]中1的个数  即所有数的和 4. 输出区间[a, b]中最大连续1的长度 对于所有的3, 4操作输出对应的答案 单个的操作都很简单  但搞在一起就有点恶心了  还好数组里的数只有0和1 线段树维护9个值 对应区间0, 1的最大长度len[i]  对应区间左端点为起点的最大0, 1长度ll

poj 3468 线段树 成段增减 区间求和

题意:Q是询问区间和,C是在区间内每个节点加上一个值 Sample Input 10 51 2 3 4 5 6 7 8 9 10Q 4 4Q 1 10Q 2 4C 3 6 3Q 2 4Sample Output 455915 1 # include <iostream> 2 # include <cstdio> 3 # include <cstring> 4 # include <algorithm> 5 # include <cmath> 6

poj 3669 线段树成段更新+区间合并

添加 lsum[ ] , rsum[ ] , msum[ ] 来记录从左到右的区间,从右到左的区间和最大的区间: #include<stdio.h> #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define maxn 50005 int rsum[maxn<<2],lsum[maxn<<2],msum[maxn<<2];//msum[]维护区间1…N中的最大连续区间长度 int

NYOJ 1068 ST(线段树之 成段更新+区间求和)

ST 时间限制:1000 ms  |  内存限制:65535 KB 难度:1 描述 "麻雀"lengdan用随机数生成了后台数据,但是笨笨的他被妹纸的问题给难住了... 已知lengdan生成了N(1=<N<=10005)个随机整数,妹子对这些数可能有以下几种操作或询问: 1,A a b c 表示给区间a到b内每个数都加上c: 2,S a b  表示输出区间a到b内的和: 3,Q a b 表示区间a到b内的奇数的个数: 为了使妹纸不口渴,所以我们决定妹纸的询问次数少一点,即

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

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

题目传送门 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 2777 Count Color (线段树成段更新+二进制思维)

题目链接:http://poj.org/problem?id=2777 题意是有L个单位长的画板,T种颜色,O个操作.画板初始化为颜色1.操作C讲l到r单位之间的颜色变为c,操作P查询l到r单位之间的颜色有几种. 很明显的线段树成段更新,但是查询却不好弄.经过提醒,发现颜色的种类最多不超过30种,所以我们用二进制的思维解决这个问题,颜色1可以用二进制的1表示,同理,颜色2用二进制的10表示,3用100,....假设有一个区间有颜色2和颜色3,那么区间的值为二进制的110(十进制为6).那我们就把