pku3468----成段更新区间求和
来源:互联网 发布:mac chrome 迅雷插件 编辑:程序博客网 时间:2024/06/08 00:50
// Creat By 郭仔 2015年3月22日5:16:23
小心越界
每次在修改节点的sum值时,如果每次都下放到叶子节点,那么复杂度会变成nlogn,还不如直接暴力(树状数组还sqrt(n)呢,虽然我不会),而且对于某些修改一大段值的问题,用线段树动态维护的时候,如果找到了要修改的大区间,可以直接在这个大区间上标记,然后改掉sum值,等下次修改或者查询时再修改或者查询它的标记值,这样就可以做到每次查询或修改都为logn,大大节省了时间。#include<cstdlib>
#include<iostream>
#include<cstring>
#include<cstdio>
#define ll(x) ((x)<<1)
#define rr(x) ((x)<<1|1)
using namespace std;
struct Node
{
int left;
int right;
__int64 value;//这里注意
int add;//标记,提高时间效率
}tree[300000];
int num[100010];
__int64 build(int l,int r,int idx)
{
int mid;
tree[idx].left=l;
tree[idx].right=r;
tree[idx].add=0;
if(l==r)
{
return tree[idx].value=num[l];//叶子节点值
}
mid=(l+r)/2;
return tree[idx].value=build(l,mid,ll(idx))+build(mid+1,r,rr(idx));//又忘了加1,囧事
}
__int64 query(int l,int r,int idx)
{
int mid;
if(tree[idx].left==l&&tree[idx].right==r)
return tree[idx].value;//
if(tree[idx].add)//接着更新,这里易错
{
tree[ll(idx)].value+=(__int64)(tree[ll(idx)].right-tree[ll(idx)].left+1)*tree[idx].add;
tree[rr(idx)].value+=(__int64)(tree[rr(idx)].right-tree[rr(idx)].left+1)*tree[idx].add;
tree[ll(idx)].add+=tree[idx].add;
tree[rr(idx)].add+=tree[idx].add;
tree[idx].add=0;
}
mid=(tree[idx].left+tree[idx].right)/2;
if(r<=mid)
return query(l,r,ll(idx));
else if(l>mid)
return query(l,r,rr(idx));
else
return query(l,mid,ll(idx))+query(mid+1,r,rr(idx));//一直忘记+1;
}
void update(int l,int r,int a,int idx)
{
int mid;
if(tree[idx].left>=l&&tree[idx].right<=r)
{
tree[idx].value+=(__int64)(tree[idx].right-tree[idx].left+1)*a;
tree[idx].add+=a;
return ;//以为这里没有更新孩子节点,所以在query中还有更新的环节
}
if(tree[idx].add)//接着更新,这里易错
{
tree[ll(idx)].value+=(__int64)(tree[ll(idx)].right-tree[ll(idx)].left+1)*tree[idx].add;
tree[rr(idx)].value+=(__int64)(tree[rr(idx)].right-tree[rr(idx)].left+1)*tree[idx].add;
tree[ll(idx)].add+=tree[idx].add;
tree[rr(idx)].add+=tree[idx].add;
tree[idx].add=0;
}
mid=(tree[idx].left+tree[idx].right)/2;
if(l<=mid)
update(l,r,a,ll(idx));//只要有一个就得更新
if(r>mid)
update(l,r,a,rr(idx));
tree[idx].value=tree[ll(idx)].value+tree[rr(idx)].value;
}
int main()
{
int i,m,n,l,r;
int a;
char ch[10];
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=1;i<=n;i++)//这里下标从1开始
scanf("%d",&num[i]);
build(1,n,1);
while(m--)
{
getchar();
cin>>ch;
//scanf("%s",ch);
if(ch[0]=='Q')
{
scanf("%d%d",&l,&r);
printf("%I64d\n",query(l,r,1));//防止越界
}
else
{
scanf("%d%d%d",&l,&r,&a);
update(l,r,a,1);
}
}
}
return 0;
}
1 0
- pku3468----成段更新区间求和
- PKU3468区间更新
- 线段树,成段更新,区间求和
- Poj 3667 Hotel 成段更新,区间合并,区间求和
- 线段树POJ3468(成段更新,区间求和)
- 线段树(成段更新,区间求和lazy操作 )
- poj 2777 Count Color (成段更新+区间求和)
- 线段树POJ3468(成段更新,区间求和)
- POJ3468 A Simple Problem with Integers 线段树 区间成段更新+区间求和
- PKU3468(A Simple Problem with Integers)线段树的成段更新
- POJ 3468 A Simple Problem with Integers 成段更新,总区间求和
- http://acm.hdu.edu.cn/showproblem.php?pid=1698 成段更新,总区间求和
- hdu 1698 Just a Hook(线段树 成段更新+总区间求和)
- 成段更新总区间求和.HDU-1698 Just…
- hdu 1698 Just a hook 线段树 成段更新~~区间求和
- NYOJ 1068 ST(线段树之 成段更新+区间求和)
- Poj 3468 A Simple Problem with Integers 成段更新,区间求和
- POJ 3468-A Simple Problem with Integers(线段树:成段更新,区间求和)
- html页面显示留白问题
- 正则表达式30分钟入门教程
- spring 注解上传文件 @RequestParam(value = "file1", required = false)
- 从CIO视角出发审视云环境下的安全议题
- 软件架构的过程
- pku3468----成段更新区间求和
- iOS —— 转场
- java.io.IOException: Too many open files
- 解决默认打开浏览器的ActivityNotFoundException异常
- Android Fragment 真正的完全解析(上)
- hdoj 1253 胜利大逃亡
- 排序算法一览
- JAVA + uploadify 3.2.1 + Spring MVC + FTP 上传图片
- Android Fragment 真正的完全解析(下)