A Simple Problem with Integers-POJ3468 区间修改+区间查询

时间:2023-03-09 18:33:58
A Simple Problem with Integers-POJ3468  区间修改+区间查询

题意:

给你n个数和2个操作,C操作是将一个区间内的每个数都加上k,Q操作是询问一个区间的和

链接:http://poj.org/problem?id=3468

思路:

线段树区间修改+区间查询

代码:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <math.h>
using namespace std;
const int MAXN=2e5+;
typedef long long ll;
ll tree[MAXN<<];
ll lazy[MAXN<<]; //lazy数组为区间修改时引进的一个标记数组
void push_up(ll node)
{
tree[node]=tree[node<<]+tree[node<<|];
}
void build(ll node,ll l, ll r)
{
if(l==r)
{
scanf("%lld",&tree[node]);
return ;
}
ll mid=(l+r)>>;
build(node<<,l,mid);
build(node<<|,mid+,r);
push_up(node);
} /*
push_down函数用来下传lazy标记,左右儿子的lazy等于父亲节点的lazy,
左儿子的区间和改变的数值为左儿子的区间长度*lazy[node]的值,右儿子同理,
下传结束后将父亲节点的lazy[node]变为0.
*/ void push_down(int node,int l,int r,int mid)
{ lazy[node<<]+=lazy[node];
lazy[node<<|]+=lazy[node];
tree[node<<]+=(mid-l+)*lazy[node];
tree[node<<|]+=(r-mid)*lazy[node];
lazy[node]=; }
void update(int node,int l,int r,int x,int y,int k) //区间修改函数
{
if(x<=l&&y>=r) //如果l,r在范围内,该区间的和直接增加(r-l+1)*k,打上lazy标记
{
tree[node]+=(r-l+)*k;
lazy[node]+=k;
return;
}
ll mid=(l+r)>>;
if(lazy[node]) //如果有lazy标记,则下传
push_down(node,l,r,mid);
if(x<=mid)
update(node<<,l,mid,x,y,k);
if(y>mid)
update(node<<|,mid+,r,x,y,k);
push_up(node); //修改他父亲区间的和
}
ll query(ll node,ll l,ll r,ll x,ll y)
{
if(x<=l&&y>=r)
return tree[node];
ll mid=(l+r)>>;
if(lazy[node])push_down(node,l,r,mid);
ll ans=;
if(x<=mid)
ans+=query(node<<,l,mid,x,y);
if(y>mid)
ans+=query(node<<|,mid+,r,x,y);
return ans;
}
int main()
{
ll n,q;scanf("%lld%lld",&n,&q);
build(,,n);
for(int i=;i<=q;i++)
{
char str[];
scanf("%s",str);
ll x,y;
if(str[]=='Q')
{
scanf("%lld%lld",&x,&y);
printf("%lld\n",query(,,n,x,y));
}
else
{
ll k;
scanf("%lld%lld%lld",&x,&y,&k);
update(,,n,x,y,k);
}
}
return ;
}