您的位置:首页 > 理论基础 > 数据结构算法

POJ 3468-线段数区间更新

2017-11-10 02:25 197 查看

POJ 3468

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.

题目大意:给你一堆数,在区间里进行各种操作,询问区间的和、注意sum、和seg的数据类型是long long

真的是艰难,经历了3个小时终于A掉了,不过还是值得的。这样一来对线段树的区间更新认识更加深刻了,回来再把区间更新的原理写出来吧,虽然不是很困,但是时间真的有点晚了,我还有点饿

区间更新、区间求和更新延迟标记时注意

标记的叠加、叠加、叠加…省略无数次叠加

Pushdown

void Pushdown(int l,int r,int i)
{//操作结果延迟标记下压子区间
//同时更新子区间区间的sum
if(tree[i].seg==0)
return ;
int m=(l+r)>>1;
tree[i<<1].seg+=tree[i].seg;//注意这里是叠加
tree[i<<1].sum+=tree[i].seg*(m-l+1);
tree[i<<1|1].seg+=tree[i].seg;
tree[i<<1|1].sum+=tree[i].seg*(r-m);
tree[i].seg=0;//清楚延迟标记
}


Update

void Update(int L,int R,int l,int r,int i,long long e)
{ //操作结果将目标区间打上延迟标记,更新路径上的sum
if(L<=l&&R>=r)
{
tree[i].seg+=e;//这里是细节
tree[i].sum+=(long long)(e*(r-l+1));
return;
}
Pushdown(l,r,i);
int m=(l+r)>>1;
if(L<=m)
Update(L,R,lson,e);
if(R>m)
Update(L,R,rson,e);
Pushup(i);
}


#include<iostream>
#include<cstdio>
#include<cstring>
#define lson l,m,i<<1
#define rson m+1,r,i<<1|1
using namespace std;
const int maxn=100005;
struct node
{
int left,right;
long long sum;
long long seg;
}tree[maxn<<2];
void Pushup(int i)
{
tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
}

void Pushdown(int l,int r,int i) {//操作结果延迟标记下压子区间 //同时更新子区间区间的sum if(tree[i].seg==0) return ; int m=(l+r)>>1; tree[i<<1].seg+=tree[i].seg;//注意这里是叠加 tree[i<<1].sum+=tree[i].seg*(m-l+1); tree[i<<1|1].seg+=tree[i].seg; tree[i<<1|1].sum+=tree[i].seg*(r-m); tree[i].seg=0;//清楚延迟标记 }

void Build(int l,int r,int i)
{
tree[i].left=l;
tree[i].right=r;
if(l==r)
{
scanf("%lld",&tree[i].sum);
return ;
}
int m=(l+r)>>1;
Build(lson);
Build(rson);
Pushup(i);
}

void Update(int L,int R,int l,int r,int i,long long e) { //操作结果将目标区间打上延迟标记,更新路径上的sum if(L<=l&&R>=r) { tree[i].seg+=e;//这里是细节 tree[i].sum+=(long long)(e*(r-l+1)); return; } Pushdown(l,r,i); int m=(l+r)>>1; if(L<=m) Update(L,R,lson,e); if(R>m) Update(L,R,rson,e); Pushup(i); }
long long Query(int L,int R,int l,int r,int i)
{//操作结果 求区间和、跟新途中延迟标记
if(L<=l&&R>=r)
{
return tree[i].sum;
}
long long ans=0;
Pushdown(l,r,i);
int m=(l+r)>>1;
if(L<=m)
ans+=Query(L,R,lson);
if(R>m)
ans+=Query(L,R,rson);
return ans;
}
int main()
{
memset(tree,0,sizeof(tree));
int N,Q;
cin>>N>>Q;
Build(1,N,1);
for(int j=1;j<=Q;j++)
{
int a,b,c;
char str;
cin>>str;
if(str=='Q')
{
cin>>a>>b;
cout<<Query(a,b,1,N,1)<<endl;
}
if(str=='C')
{
cin>>a>>b>>c;
Update(a,b,1,N,1,c);
}
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm题解 数据结构