A Simple Problem with Integers
Time Limit: 5000MS | | Memory Limit: 131072K | | | | Case Time Limit: 2000MS |
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.
Input
The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000. The second line contains N numbers, the initial values of A1, A2, ... , AN. -1000000000 ≤ Ai ≤ 1000000000. Each of the next Q lines represents an operation. "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.
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
/**
题意:
给出一列数,提供两个操作:1.输出区间[l, r]所有书的和; 2.将区间[l, r]所有数加上C。
与上一道相同,也是使用Lazy标记。但是,这道题还要实现多次查询。
在查询时,也需要像成段时那样将lazy标记一直向下更新,并且,需要将维护的和同步更新.
**/
#include <map>
#include <set>
#include <list>
#include <queue>
#include <stack>
#include <cmath>
#include <ctime>
#include <vector>
#include <bitset>
#include <cstdio>
#include <string>
#include <numeric>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
int dx[4]={-1,1,0,0};
int dy[4]={0,0,-1,1};//up down left right
bool inmap(int x,int y,int n,int m){if(x<1||x>n||y<1||y>m)return false;return true;}
int hashmap(int x,int y,int m){return (x-1)*m+y;}
#define eps 1e-8
#define inf 0x7fffffff
#define debug puts("BUG")
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define read freopen("in.txt","r",stdin)
#define write freopen("out.txt","w",stdout)
#define Mem(a,x) memset(a,x,sizeof(a))
#define maxn 100005
LL col[maxn<<2];//延迟标记
LL sum[maxn<<2];//需要维护的值
void PushUp(int rt)//向上更新需要维护的值
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void PushDown(int rt,int len)//向下传递延迟标记
{
if(col[rt])
{
col[rt<<1] +=col[rt];//在这里延迟标记成为了可以累加的和.左子树累加
col[rt<<1|1]+=col[rt];//右子树累加
sum[rt<<1] +=(len-(len>>1))*col[rt];//更新左子树sum
sum[rt<<1|1]+=(len>>1)*col[rt];//更新右子树sum
col[rt]=0;//删除标记
}
}
void build(int l,int r,int rt)
{
if(l==r)
{
scanf("%lld",&sum[rt]);//利用递归,可以按照顺序进行赋值
col[rt]=0;
return;
}
int m=(l+r)>>1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int L,int R,int key,int l,int r,int rt)
{
int len=(r-l+1);
if(L<=l&&r<=R)
{
col[rt]+=key;//标记累加
sum[rt]+=len*key;//更细当前的sum
return ;
}
PushDown(rt,len);//标记传递
int m=(l+r)>>1;
if(L<=m)
update(L,R,key,lson);
if(R>m)
update(L,R,key,rson);
PushUp(rt);//更新sum
}
LL query(int L,int R,int l,int r,int rt)
{
int len=(r-l+1);
if(L<=l&&r<=R)
{
return sum[rt];//查到了sum,返回
}
PushDown(rt,len);//标记传递
int m=(l+r)>>1;
LL ans=0;
if(L<=m)//与左子树的区间有交集
ans+=query(L,R,lson);
if(R>m)//与右子树的区间有交集
ans+=query(L,R,rson);
PushUp(rt);//因为标记已经传递,传递的过程中素描也进行了更新,因此需要更新rt的sum
return ans;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
build(1,n,1);//建树
for(int i=0;i<m;i++)
{
char s[3];
scanf("%s",s);
if(s[0]=='Q')//查询
{
int l,r;
scanf("%d%d",&l,&r);
printf("%lld\n",query(l,r,1,n,1));
}
else
{
int l,r,key;
scanf("%d%d%d",&l,&r,&key);
update(l,r,key,1,n,1);//更新
}
}
return 0;
}
|