线段树(区间更新求和)
来源:互联网 发布:js 判断包含 正则 编辑:程序博客网 时间:2024/05/02 04:19
//poj 3468
#include <iostream>
using namespace std;
#define MAX 100100
struct node
{
int left, right;
//区间和
long long sum;
//增加量
long long add;
//求分割点
int get_mid() {
return (left + right) / 2;
}
//求区间长度
int get_dis() {
return right - left + 1;
}
};
node tree[MAX * 3];
long long d[MAX];
//建树
long long build(int left, int right, int loc)
{
int LL = loc << 1;
int RR = LL | 1;
tree[loc].left = left;
tree[loc].right = right;
//初始增量为零
tree[loc].add = 0;
if (left == right) {
return tree[loc].sum = d[left];
}
int mid = tree[loc].get_mid();
return tree[loc].sum = build(left, mid, LL) + build(mid + 1, right, RR);
}
//更新节点
void update(int left, int right, long long value, int loc)
{
int LL = loc << 1;
int RR = LL | 1;
//如果是某个节点,直接增加增量。
if (tree[loc].left == left && tree[loc].right == right)
{
tree[loc].add += value;
return ;
}
//不管要更新的区间位于什么位置上,根节点的值必定增加((right - left + 1) * value);
tree[loc].sum += (long long)(right - left + 1) * value;
//递归更新左右节点
int mid = tree[loc].get_mid();
if (right <= mid) {
update(left, right, value, LL);
} else if (mid < left) {
update(left, right, value, RR);
} else {
update(left, mid, value, LL);
update(mid + 1, right, value, RR);
}
}
//查询区间值
long long query(int left, int right, int loc)
{
int LL = loc << 1;
int RR = LL | 1;
//刚好查询的区间和是一个节点的区间和
if (tree[loc].left == left && tree[loc].right == right) {
return tree[loc].sum + (long long)tree[loc].get_dis() * tree[loc].add;
}
//区间有增量
if (tree[loc].add) {
//先更新本节点的区间和
tree[loc].sum += (long long)tree[loc].get_dis() * tree[loc].add;
//增量向左右节点传递
tree[LL].add += tree[loc].add;
tree[RR].add += tree[loc].add;
//本节点增量设置为零
tree[loc].add = 0;
}
//递归查询左右子树
int mid = tree[loc].get_mid();
if (right <= mid) {
return query(left, right, LL);
} else if (mid < left) {
return query(left, right, RR);
} else {
return query(left, mid, LL) + query(mid + 1, right, RR);
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("3468.txt", "r", stdin);
#endif
int n, q;
while (cin >> n >> q)
{
int i;
for (i = 1; i <= n; i++) {
scanf("%lld", &d[i]);
}
build(1, n, 1);
char op[5];
int a, b, c;
while (q--) {
scanf("%s", &op);
if (op[0] == 'Q') {
scanf("%d %d", &a, &b);
if (a > b) {
int temp = a;
a = b;
b = temp;
}
printf("%lld\n", query(a, b, 1));
} else {
scanf("%d %d %lld", &a, &b, &c);
if (a > b) {
int temp = a;
a = b;
b = temp;
}
update(a, b, c, 1);
}
}
}
return 0;
}
- 线段树(区间更新求和)
- 线段树(单点更新,区间求和)
- 线段树 (区间更新求和)
- 线段树区间更新+求和
- poj3468 线段树区间更新,区间求和
- 线段树总结(单点更新,区间更新,区间求和,区间求最值)
- hdu1394——线段树(单点更新 区间求和)
- poj 3468 (线段树区间更新及求和)
- 线段树(成段更新,区间求和lazy操作 )
- HDU 1166 单点更新 区间求和(ZKW 线段树)
- hdu1166 敌兵布阵(线段树单点更新+区间求和)
- HDU1698(线段树区间更新求和)
- poj2352Stars【线段树单点更新区间求和】
- 线段树单点更新 区间求和,求最值
- leetCode_线段树、单点更新、区间求和
- 线段树,成段更新,区间求和
- HDU1166 线段树区间求和,单点更新
- CodeForces 52C Circular RMQ(区间循环线段树,区间更新,区间求和)
- linux GDB调试
- CSS3学习----选择器、字体
- v$queue中的type栏位的意义
- 管理处理器的亲和性(affinity)
- C/C++内存分配方式以及存储分区
- 线段树(区间更新求和)
- 最少试几次才可以找出鸡蛋不会被摔碎的最高楼层?
- github使用总结
- What is the Difference Between `apt-get purge` and `apt-get remove`?
- ajax案例---以GET和POST方式异步提交数据给后台
- Fruit Ninja II (微积分)
- php输出中文乱码问题
- php中创建用户和数据库的连接
- Android UI 设计 选项卡组件和ListView组件结合模拟新浪微博