您的位置:首页 > 其它

POJ 3468 A Simple Problem with Integers(线段树)

2016-02-22 15:54 295 查看
给出了一个序列,你需要处理如下两种询问。

"C a b c"表示给[a, b]区间中的值全部增加c (-10000 ≤ c ≤ 10000)。

"Q a b" 询问[a, b]区间中所有值的和。

第一行包含两个整数N, Q。1 ≤ N,Q ≤ 100000.

第二行包含n个整数,表示初始的序列A (-1000000000 ≤ Ai ≤ 1000000000)。

接下来Q行询问,格式如题目描述。

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


这道题也比较简单,成段更新

体现了线段树的好处

不过要注意这里增加了两个方法  pushdown和pushup

pushup就是向上更新,也就是说父节点的和是两个子节点的和相加 从叶子节点累加上去到了根节点的话,最终根节点的和就是所有叶子节点的值加起来

有点像BOSS拿的钱就是各个小弟拿的钱加起来  就那么个意思~

pushdown就是向下更新,也就是说  比如你输入了 C 1 4 1也就是在第1个数到第4个数全部加1 

首先你就要找到1 到4 然后在1到4 下面的1 到 2 和 3 到 4 把要加的数也就是1 加上去 依次类推在 1 到 2 下面的1 和 2 加上1

那么结果就是你在 1 2 3 4这四个叶子节点中的值都加了1,在这里有两个要维护的域 一个是“加多少” tree[i].add ,另外一个是“加了之后是多少” tree[i].sum

在update中的



if(A<=l&&B>=r)
{
tree[i].add+=C;
tree[i].sum+=C*(r-l+1);
return ;
}

r-l+1是这段区间的长度也就是线段长度,比如上面所说的例子如果恰好是1 到 4 的话直接可以在 1 到4线段中加上 1*4=4 此次update就完成了
说到这里已经很清楚了,下面上代码:#include<cstdio>
#define N 100005
int n,m;
long long num
;
struct node
{
int l,r;
long long sum;
long long add;
} tree[N<<2];
void pushup(int i)
{

tree[i].sum=tree[i<<1].sum+tree[i<<1|1].sum;
}
void build(int l,int r,int i)
{
tree[i].l=l;
tree[i].r=r;
if(l==r)
{
tree[i].sum=num[l];
return ;
}
int mid=(l+r)>>1;
build(l,mid,i<<1);
build(mid+1,r,i<<1|1);
pushup(i);
}
void pushdown(int rt,int dis)
{
if(tree[rt].add)
{
tree[rt<<1].add+=tree[rt].add;
tree[rt<<1|1].add+=tree[rt].add;
tree[rt<<1].sum+=tree[rt].add*(dis-(dis>>1));
tree[rt<<1|1].sum+=tree[rt].add*(dis>>1);
tree[rt].add=0;
}
}
void update(int A,int B,int C ,int l,int r,int i)
{
if(A<=l&&B>=r)
{
tree[i].add+=C;
tree[i].sum+=C*(r-l+1);
return ;
}
pushdown(i,r-l+1);
int mid=(l+r)>>1;
if(A<=mid)update(A,B,C,l,mid,i<<1);
if(B>mid)update(A,B,C,mid+1,r,i<<1|1);
pushup(i);
}
long long query(int A,int B,int l,int r,int i)
{

if(A<=l&&B>=r)
{
return tree[i].sum;
}
pushdown(i,r-l+1);
long long ans=0;
int mid=(l+r)>>1;
if(A<=mid) ans+=query(A,B,l,mid,i<<1);
if(B>mid) ans+=query(A,B,mid+1,r,i<<1|1);
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
scanf("%I64d",&num[i]);

build(1,n,1);
while(m--)
{
char s[6];
int a,b,c;
scanf("%s",&s);
if(s[0]=='C')
{
scanf("%d%d%d",&a,&b,&c);
update(a,b,c,1,n,1);
}
else
{
scanf("%d%d",&a,&b);
printf("%I64d\n",query(a,b,1,n,1));

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