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. Input The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000. 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
|
[Submit] [Go Back] [Status] [Discuss]
Link: http://poj.org/problem?id=3468
题意;给出一个数列,两种操作,Q为查询区间总和,C为区间更新
思路:线段树区间更新区间和值查询
update:复习线段树,更新了一下板子;
AC code:
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <string>
#include <map>
using namespace std;
#define LL long long
#define INF 0x3f3f3f3f
const int MAXN= 100000+50;
//线段树区间更新求最值
struct Node
{
int l,r; //区间的左右端点
LL Max;
LL Min;
LL Sum;
LL Lazy;
}segTree[MAXN<<2];
//向上更新
void PushUp(int i)
{
segTree[i].Max=max(segTree[i<<1].Max,segTree[(i<<1)|1].Max);
segTree[i].Min=min(segTree[i<<1].Min,segTree[(i<<1)|1].Min);
segTree[i].Sum=segTree[i<<1].Sum+segTree[(i<<1)|1].Sum;
}
//标记下移
void PushDown(int i,int x){
if(segTree[i].Lazy)
{
segTree[i<<1].Lazy += segTree[i].Lazy;
segTree[(i<<1)|1].Lazy += segTree[i].Lazy;
segTree[i<<1].Sum += segTree[i].Lazy*(x-(x>>1));
segTree[(i<<1)|1].Sum += segTree[i].Lazy*(x>>1);
segTree[i].Lazy=0;
}
}
//一般调用Build(1,1,n);
void Build(int i,int l,int r)
{
segTree[i].l=l;
segTree[i].r=r;
segTree[i].Max=0;
segTree[i].Min=INF;
segTree[i].Sum=0;
segTree[i].Lazy=0;
if(l==r)
{
int num=1;
scanf("%lld",&num);
segTree[i].Max=num;
segTree[i].Min=num;
segTree[i].Sum=num;
return;
}
int mid=(l+r)>>1;
Build(i<<1,l,mid);
Build((i<<1)|1,mid+1,r);
PushUp(i);
}
//根节点i的区间(l,r)增加c
void Add(int i,int l,int r,int c)
{
if(l<=segTree[i].l && segTree[i].r<=r)
{
segTree[i].Lazy += c;
segTree[i].Max += c;
segTree[i].Min += c;
segTree[i].Sum += c*(segTree[i].r-segTree[i].l+1);
return;
}
PushDown(i,segTree[i].r-segTree[i].l+1);
int mid=(segTree[i].l+segTree[i].r)>>1;
if(l<=mid) Add(i<<1,l,r,c); //区间在左边
if(r>mid) Add((i<<1)|1,l,r,c); //区间在右边
PushUp(i);
}
//查询l-r的总和,查询同时更新
LL QuerySum(int i,int l,int r){
if(l<=segTree[i].l && segTree[i].r<=r){
return segTree[i].Sum;
}
PushDown(i,segTree[i].r-segTree[i].l+1);
int mid=(segTree[i].l+segTree[i].r)>>1;
//判断区间并返回
LL res=0;
if(l<=mid) res+=QuerySum(i<<1,l,r);
if(r>mid) res+=QuerySum((i<<1)|1,l,r);
return res;
}
LL QueryMin(int i,int l,int r){
if(l<=segTree[i].l && segTree[i].r<=r){
return segTree[i].Min;
}
PushDown(i,segTree[i].r-segTree[i].l+1);
int mid=(segTree[i].l+segTree[i].r)>>1;
LL res=INF;
if(l<=mid) res=min(QueryMin(i<<1,l,r),res);
if(r>mid) res=min(QueryMin((i<<1)|1,l,r),res);
return res;
}
LL QueryMax(int i,int l,int r){
if(l<=segTree[i].l && segTree[i].r<=r){
return segTree[i].Max;
}
PushDown(i,segTree[i].r-segTree[i].l+1);
int mid=(segTree[i].l+segTree[i].r)>>1;
LL res=0;
if(l<=mid) res=max(res,QueryMax(i<<1,l,r));
if(r>mid) res=max(res,QueryMax((i<<1)|1,l,r));
return res;
}
int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
Build(1,1,n);
while(m--){
char str[5];
int l,r;
scanf("%s%d%d",str,&l,&r);
if(str[0]=='C'){
int c;
scanf("%d",&c);
Add(1,l,r,c);
}
else printf("%lld\n",QuerySum(1,l,r) );
}
}
return 0;
}