奇偶线段树(区间更新)
来源:互联网 发布:美术史论研究生知乎 编辑:程序博客网 时间:2024/06/13 11:17
题目链接:http://ccnu.acmclub.com/index.php?app=problem_title&id=613&problem_id=23875
题意:给你一个长度为n的数组(下标从1开始)。进行如下操作。
(1)1 x y v :表示将下标=(x,x+2,x+4,x+6,.......并且<=y)的元素全部+v;
(2)2 x y :查询[x,y]闭区间的元素和。
思路:构造2棵线段树。将区间[1,3,...,2k - 1]改为[1,2,...,k],用一棵线段树统计这个区间内的和。将区间[2,4,...,2k]改为[1,2,...,k],用一棵线段树统计这个区间内的和。剩下为普通的区间更新即可。
代码:
#include <iostream>#include <stdio.h>#include <string.h>#include <math.h>#include <algorithm>#include <string>using namespace std;#define lson l, m, rt << 1#define rson m + 1, r, rt << 1 | 1#define ceil(x, y) (((x) + (y) - 1) / (y))const int N = 1e5 + 10;const int INF = 0x7f7f7f7f;struct Node {long long sum;long long add;};Node node[3][N << 2];//0 偶线段树 1 奇线段树long long a[N];void pushup(int op, int rt) {node[op][rt].sum = node[op][rt << 1].sum + node[op][rt << 1 | 1].sum;}void pushdown(int op, int rt, int len) {int lenl = (len - (len >> 1));int lenr = (len >> 1);if (node[op][rt].add) {node[op][rt << 1].sum += 1LL * lenl * node[op][rt].add;node[op][rt << 1 | 1].sum += 1LL * lenr * node[op][rt].add;node[op][rt << 1].add += node[op][rt].add;node[op][rt << 1 | 1].add += node[op][rt].add;node[op][rt].add = 0;}}void build(int op, int l, int r, int rt) {node[op][rt].add = 0;if (l == r) {if (op)node[op][rt].sum = a[2 * l - 1];elsenode[op][rt].sum = a[2 * l];return ;}int m = (l + r) >> 1;build(op, lson);build(op, rson);pushup(op, rt);}void update(int op, int L, int R, long long c, int l, int r, int rt) {if (L <= l && r <= R) {node[op][rt].sum += 1LL * (r - l + 1) * c;node[op][rt].add += c;return ;}pushdown(op, rt, r - l + 1);int m = (l + r) >> 1;if (L <= m)update(op, L, R, c, lson);if (R > m)update(op, L, R, c, rson);pushup(op, rt);}long long query(int op, int L, int R, int l, int r, int rt) {if (L <= l && r <= R) {return node[op][rt].sum;}pushdown(op, rt, r - l + 1);int m = (l + r) >> 1;long long ql = 0, qr = 0;if (L <= m)ql = query(op, L, R, lson);if (R > m)qr = query(op, L, R, rson);pushup(op, rt);return ql + qr;}int main() {int t_case;scanf("%d", &t_case);for (int i_case = 1; i_case <= t_case; i_case++) {int n, m;int no, ne;bool flag = false;scanf("%d%d", &n, &m);for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);no = ceil(n, 2);ne = n - no;build(1, 1, no, 1);if (ne) {//是否需要建偶线段树build(0, 1, ne, 1);flag = true;}for (int i_q = 1; i_q <= m; i_q++) {int op, l, r;scanf("%d%d%d", &op, &l, &r);if (op == 1) {long long v;scanf("%lld", &v);if ((l + r) & 1)r--;if (l & 1)update(1, ceil(l, 2), ceil(r, 2), v, 1, no, 1);else update(0, ceil(l, 2), ceil(r, 2), v, 1, ne, 1);}else {int Ol = ceil((l & 1 ? l : l + 1), 2);int Or = ceil((r & 1 ? r : r - 1), 2);int El = ceil((l & 1 ? l + 1 : l), 2);int Er = ceil((r & 1 ? r - 1 : r), 2);long long qo = 0, qe = 0;if (Ol <= Or)//区间合法qo = query(1, Ol, Or, 1, no, 1);if (flag && El <= Er)qe = query(0, El, Er, 1, ne, 1);printf("%lld\n", qo + qe);}}}return 0;}
0 0
- 奇偶线段树(区间更新)
- 线段树(单点更新+区间更新)
- 线段树区间更新
- 线段树区间更新
- 线段树 区间更新
- 线段树区间更新
- 线段树-区间更新
- 线段树区间更新
- 线段树区间更新
- 线段树区间更新
- 区间更新线段树
- 线段树区间更新
- 线段树 区间更新
- 线段树区间更新
- POJ2777(线段树区间更新+LAZY)
- POJ3468(线段树区间更新)
- 线段树(区间更新求和)
- 线段树(单点更新,区间求和)
- 【Ajax技术】使用XHR对象发送和接受数据
- LeetCode: Implement pow(x, n).
- Android SwipeBackLayout返回黑屏的处理
- Anroid 布局管理器
- list 转换为 str
- 奇偶线段树(区间更新)
- Boostrap入门+样式学习--贰--(慕课网大漠《玩转bootstrap》[基础])
- LVS基于DR模型实现简单负载均衡集群和持久连接
- Git 多账号使用
- Linux gcc 使用以及库文件的编译
- 杭电 3342 Legal or Not(拓扑排序)
- Java集群优化——dubbo+zookeeper构建高可用分布式集群
- spring 使用c3po连接池
- hdu 1242 Rescue (BFS+优先队列)