题目大意

一个数列,每次操作可以是将某区间数字都加上一个相同的整数,也可以是询问一个区间中所有数字的和。(这里区间指的是数列中连续的若干个数)对每次询问给出结果。

思路

对于区间的查找更新操作,可以考虑使用伸展树、线段树等数据结构。这里使用线段树来解决。需要注意的是,对于一个区间的增加操作,如果每次都走到叶子节点进行更新,则必定超时,因此lazy方法来解决。即如果能从当前节点获得所需要的信息,则不必走到子节点。

实现(c++)

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdio.h>
using namespace std;
#define MAX_COUNT 100005
#define MAX(a, b) a>b? a:b
#define MIN(a, b) a<b? a:b//查找两个相交的区间的并长度(即两个区间覆盖的总长度)
int Interval(int beg1, int end1, int beg2, int end2){int tmp = MAX(end1, end2); //注意不要  MAX(end1, end2) -MIN(beg1, beg2), 因为这样做在编译的时候宏定义展开,//和三目运算符一块,优先级导致结果出错!!!!
tmp -= MIN(beg1, beg2);return (end1 - beg1 + end2 - beg2) - tmp + 1;
}int gNumCount, gQueryCount; //总的数字的数目,总的查询次数int gNumber[MAX_COUNT]; //线段树节点的数组//线段树节点的定义
struct TreeNode{int begin;    //该节点覆盖区间的左边界int end;    //该节点覆盖区间的右边界long long sum;    //该节点覆盖区间的当前sum值,不包括 inc 可能增加的那些值(即实际的和应该为 sum + inc *(end - begin+1)long long inc;    //该节点覆盖区间中的那些点 应该被增加的值(注意是该区间的所有点)
};struct TreeNode gTreeNodes[MAX_COUNT*4];//自底向上的更新,将左右子的 sum 值相加得到 该节点的sum值
void PushUp(int node_index){int left_child = 2 * node_index + 1;int right_child = 2 * node_index + 2;gTreeNodes[node_index].sum = gTreeNodes[left_child].sum + gTreeNodes[right_child].sum;
}//自顶向下的更新操作,当该节点不能被查询区间全部覆盖,则需要向下走,去其子节点位置进行查询
//在查询之前,需要将 inc 值传递到子节点,同时该节点的sum值更新,inc值清零
void PushDown(int node_index){TreeNode* node = gTreeNodes + node_index;int left_child = 2 * node_index + 1;int right_child = 2 * node_index + 2;node->sum += node->inc*(node->end - node->begin + 1);gTreeNodes[left_child].inc += node->inc;gTreeNodes[right_child].inc += node->inc;node->inc = 0;
}
void BuildTree(int node_index, int beg, int end){TreeNode* node = gTreeNodes + node_index;node->inc = node->sum = 0;node->begin = beg;node->end = end;if (beg ==  end){node->sum = gNumber[beg];return;}int mid = (beg + end) / 2, left_child = 2 * node_index + 1, right_child = 2 * node_index + 2;BuildTree(left_child, beg, mid);BuildTree(right_child, mid + 1, end);//自底向上更新
    PushUp(node_index);
}void Add(int node_index, int beg, int end, long long c){TreeNode* node = gTreeNodes + node_index;int left_child = 2 * node_index + 1, right_child = 2 * node_index + 2, mid = (node->begin + node->end) / 2;if (node->begin > end || node->end < beg){return;}//如果当前结点被查询区间全部覆盖,则不向下传递,直接将inc值增加if (node->begin >= beg && node->end <= end){node->inc += c;return;}//如果节点不能被查询区间全部覆盖,则需要分裂节点向下传递,此时的sum值需要增加(inc * 两区间重合的长度)//而同时 inc 值保持不变node->sum += (Interval(node->begin, node->end, beg, end) * c);int end1 = MIN(end, mid);int beg1 = MAX(beg, mid + 1);Add(left_child, beg, end1, c);Add(right_child, beg1, end, c);
}long long QuerySum(int node_index, int beg, int end){TreeNode* node = gTreeNodes + node_index;
//    printf("node %d's sum = %d\n", node_index, gTreeNodes[node_index].sum);
//    printf("node->beg = %d, node->end = %d, beg = %d, end = %d\n", node->begin, node->end, beg, end);int left_child = 2 * node_index + 1, right_child = 2 * node_index + 2, mid = (node->begin + node->end) / 2;long long sum = 0;if (node->begin > end || node->end < beg){return sum;}if (node->begin >= beg && node->end <= end){sum  += (node->sum + node->inc*(node->end - node->begin + 1));}else{//向下分裂的更新操作
        PushDown(node_index);int end1 = MIN(end, mid);int beg1 = MAX(beg, mid + 1);long long sum_left = QuerySum(left_child, beg, end1);long long sum_right = QuerySum(right_child, beg1, end);sum += (sum_left + sum_right);}return sum;
}int main(){scanf("%d %d", &gNumCount, &gQueryCount);for (int i = 0; i < gNumCount; i++){scanf("%d", gNumber + i);}BuildTree(0, 0, gNumCount - 1);char op;int a, b;long long c;long long result;for (int i = 0; i < gQueryCount; i++){getchar();scanf("%c", &op);if (op == 'C'){scanf("%d %d %lld", &a, &b, &c);Add(0, a- 1, b-1, c);/*for (int k = 0; k < 27; k++){printf("node[%d]'s sum = %lld, inc = %lld\n", k, gTreeNodes[k].sum, gTreeNodes[k].inc);}*/}else if (op == 'Q'){scanf("%d %d", &a, &b);result = QuerySum(0, a-1, b-1);printf("%lld\n", result);}}return 0;
}

poj_3468 线段树相关推荐

  1. 二逼平衡树——树套树(线段树套Splay平衡树)

    题面 Bzoj3196 解析 线段树和Splay两棵树套在一起,常数直逼inf,但最终侥幸过了 思路还是比较简单, 在原数组维护一个下标线段树,再在每一个线段树节点,维护一个对应区间的权值Splay. ...

  2. 线段树——HDU - 1698

    题目含义 就是初始化一堆数为1 可以经过操作把一个区间的数都改变 并求这堆数的总大小 题目分析 有一个 #include<iostream> #include<stdio.h> ...

  3. BZOJ.1558.[JSOI2009]等差数列(线段树 差分)

    BZOJ 洛谷 首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做. 这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B ...

  4. 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

    不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...

  5. [bzoj1582][Usaco2009 Hol]Holiday Painting 节日画画_线段树

    Holiday Painting 节日画画 bzoj-1582 Usaco-2009 Hol 题目大意:给定两个n*m的01网格图.q次操作,每次将第二个网格图的子矩阵全部变成0或1,问每一次操作后两 ...

  6. codefores 786B. Legacy(最短路,线段树优化拆点,好题)

    题目链接 B. Legacy time limit per test2 seconds memory limit per test256 megabytes inputstandard input o ...

  7. 【题解】BZOJ 3065: 带插入区间K小值——替罪羊树套线段树

    题目传送门 题解 orz vfk的题解 3065: 带插入区间K小值 系列题解 一 二 三 四 惨 一开始用了一种空间常数很大的方法,每次重构的时候merge两颗线段树,然后无限RE(其实是MLE). ...

  8. 树链剖分+线段树 HDOJ 4897 Little Devil I(小恶魔)

    题目链接 题意: 给定一棵树,每条边有黑白两种颜色,初始都是白色,现在有三种操作: 1 u v:u到v路径(最短)上的边都取成相反的颜色 2 u v:u到v路径上相邻的边都取成相反的颜色(相邻即仅有一 ...

  9. bzoj1095: [ZJOI2007]Hide 捉迷藏 线段树维护括号序列 点分治 链分治

    这题真是十分难写啊 不管是点分治还是括号序列都有一堆细节.. 点分治:时空复杂度$O(n\log^2n)$,常数巨大 主要就是3个堆的初始状态 C堆:每个节点一个,为子树中的点到它父亲的距离的堆. B ...

  10. POJ 2528 Mayor's posters(线段树)

    题目大意 贴海报.每张海报的高度都是一样的,唯独宽度不一样.每张海报只能占用整数倍的单位线段长度,贴了 n(n<=10000) 张海报之后,有几张能够看见(有一个角能看见这张海报也算被看见了)? ...

最新文章

  1. php创建多级目录完整封装类操作
  2. python JSON ValueError: Expecting property name: line 1 column 2 (char 1)
  3. webservice linux 杀进程
  4. 函数体中的全局变量与局部变量
  5. ip, tcp, udp, icmp header
  6. Mac OS下Tomcat native-APR的安装
  7. winedt (latex 编译器)解决中文的问题(CJK CTEX)
  8. 使用递归函数求解字符串的逆置问题
  9. linux scp 非22端口,[ssh scp sftp] 连接远程ssh非22端口的服务器方法
  10. ISP 和摄像头基本知识
  11. redis数据一致性
  12. python音频转文字腾讯_Python生成腾讯云实时音视频的UserSig签名
  13. 高等数学学习笔记——第六十讲——向量值函数的导数与积分
  14. 微软浏览器edge对日期Date对象format(yyyy-mm-dd)/getDiff()方法不识别
  15. 游戏辅助小助手框架构想
  16. 解决WSL2报错(请启用虚拟机平台 Windows 功能并确保在 BIOS 中启用虚拟化[已退出进程,代码为 4294967295])
  17. 【数据结构——哈夫曼树及其应用】
  18. 上门家教app开发的前景
  19. python数据质量检查
  20. wix log_如何正确地从Wix切换到WordPress(逐步操作)

热门文章

  1. 系统内核快速编译并替换的方法
  2. velocity 变量 获取_velocity 怎么得到项目根路径
  3. 华为的手册和官网视频,学习网络基础
  4. 《算法图解》之狄克斯特拉算法
  5. oracle和mysql数据实时同步_Canal 实现 Mysql数据库实时数据同步
  6. 3726.调整数组-AcWing题库
  7. 参数模型 非参数模型 生成模型 判别模型
  8. local.china java_java-JDBC无法登录到LocalDB实例,但是在SSMS中,...
  9. gradle 不支持多级子模块_Apache NetBeans 11.0 正式发布 支持Java 12
  10. 二等水准数据平差_二等水准平差软件