博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ - 3468 A Simple Problem with Integers(线段树区间更新,区间查询)
阅读量:5250 次
发布时间:2019-06-14

本文共 3123 字,大约阅读时间需要 10 分钟。

1、给出了一个序列,你需要处理如下两种询问。

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

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

2、线段树单点更新太费时,所以使用区间更新

3、

#include 
#define L(root) ((root) << 1)#define R(root) (((root) << 1) + 1)const int MAXN = 100001;int numbers[MAXN];struct st{ // 区间范围 int left, right; // 更新值、区间总和 long long delta, sum;} st[MAXN * 4];// 建树代码基本不变void build(int root, int l, int r){ st[root].left = l, st[root].right = r, st[root].delta = 0; if (l == r) { st[root].sum = numbers[l]; return; } int m = l + ((r - l) >> 1); build(L(root), l, m); build(R(root), m + 1, r); st[root].sum = st[L(root)].sum + st[R(root)].sum;}long long query(int root, int l, int r){ // 如查询区间恰等于节点区间,直接返回该区间总和即可 if (st[root].left == l && st[root].right == r) { return st[root].sum; } // 否则需将当前区间的“缓冲”值更新下去并修正各节点区间的总和 if (st[root].delta) { st[L(root)].delta += st[root].delta; st[R(root)].delta += st[root].delta; st[L(root)].sum += st[root].delta * (st[L(root)].right - st[L(root)].left + 1); st[R(root)].sum += st[root].delta * (st[R(root)].right - st[R(root)].left + 1); st[root].delta = 0; } int m = st[root].left + ((st[root].right - st[root].left) >> 1); if (r <= m) { return query(L(root), l, r); } else if (l > m) { return query(R(root), l, r); } else { return query(L(root), l, m) + query(R(root), m + 1, r); }}void update(int root, int l, int r, long long v){ // 如变更区间恰等于节点区间,只修正当前节点区间即可 if (st[root].left == l && st[root].right == r) { st[root].delta += v; st[root].sum += v * (r - l + 1); return; } // 否则需向下修正相关节点区间 if (st[root].delta) { st[L(root)].delta += st[root].delta; st[R(root)].delta += st[root].delta; st[L(root)].sum += st[root].delta * (st[L(root)].right - st[L(root)].left + 1); st[R(root)].sum += st[root].delta * (st[R(root)].right - st[R(root)].left + 1); st[root].delta = 0; } int m = st[root].left + ((st[root].right - st[root].left) >> 1); if (r <= m) { update(L(root), l, r, v); } else if (l > m) { update(R(root), l, r, v); } else { update(L(root), l, m, v); update(R(root), m + 1, r, v); } // 同时一定要记得修正当前节点区间的总和 st[root].sum = st[L(root)].sum + st[R(root)].sum;}int main(){ int N, Q; while (scanf("%d%d", &N, &Q) != EOF) { for (int i = 1; i <= N; ++i) { scanf("%d", &numbers[i]); } build(1, 1, N); char cmd; int l, r; long long v; while (Q--) { scanf(" %c", &cmd); scanf("%d%d", &l, &r); switch (cmd) { case 'Q': printf("%lld\n", query(1, l, r)); break; case 'C': scanf("%lld", &v); if (v) { update(1, l, r, v); } break; } } } return 0;}
View Code

 

转载于:https://www.cnblogs.com/bofengyu/p/4957239.html

你可能感兴趣的文章
centos7 配置ftp服务器
查看>>
【区间DP】释放囚犯
查看>>
C语言经典代码段
查看>>
HDU - 4352 XHXJ's LIS
查看>>
php2
查看>>
labview下载地址
查看>>
javascript总结37:DOM:innerText 和 innerHTML
查看>>
ps快捷键
查看>>
oracle10g环境搭建
查看>>
linux 安装及开发环境
查看>>
Java JDK 环境配置
查看>>
C# 占位符
查看>>
Eclipse 或者 Myeclipse 提示选择工作空间设置
查看>>
【Leafletjs】6.Control.Loading推展-在地图上边框添加加载动态条
查看>>
GDSOI2019划水记
查看>>
连接mysql && ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)
查看>>
零位扩展和符号位扩展
查看>>
close_socket断开连接的方式
查看>>
javascript 学习总结(八)属性定义方法
查看>>
Spring Cloud(三):声明式调用
查看>>