hdu1698 Just a Hook 【区间修改】(模板题)
<题目链接>
题目大意:
一段线段由n条小线段组成,每次操作把一个区间的小线段变成金银铜之一(金的价值为3,银为2,铜为1),最初可当做全为铜;最后求这条线段的总价值。
解题分析:
此题为线段树区间修改的一道模板题,区间修改的重点就是懒惰标记,即线面代码中的 lazy[]数组,因为我们主要想求的是某一区间的总和,而对该区间内每一个离散点的具体值没有兴趣,所以,当我们进行区间修改的时候,只需要修改该区间所对应节点的值,同时用懒惰标记记录(我认为懒惰标记实际上是指该节点的所有子节点的实际值)。如果题目没有要求访问到或者更新到这些子节点的话,我们就可以省下许多步骤,不用将每一次操作的区间内的每一个离散点(对应的叶子节点以及对应路径上的所有节点的值全部更新)。具体实现见代码。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = + ;
int lazy[maxn << ], sum[maxn << ]; void PushUp(int rt) { sum[rt] = sum[rt << ] + sum[rt << | ]; } void pushdown(int rt, int len) //将懒惰标记传递给该节点的左右儿子,同时更新该节点左右儿子的sum值(对应区间总值)
{
if (lazy[rt]) //如果lazy不是0,则说明该区间被修改过
{
lazy[rt << ] = lazy[rt];
lazy[rt << | ] = lazy[rt];
sum[rt << ] = lazy[rt] * (len - (len >> )); //注意这种求左儿子区间长度的方法,因为左儿子包含了mid,所以可以这样求 (len-(len>>1))
sum[rt << | ] = lazy[rt] * (len >> );
lazy[rt] = ; //该节点的lazy重新置0
}
} void build(int rt, int l, int r)
{
lazy[rt] = ;
if (l == r)
{
sum[rt] = ; //初始为铜,值为1
return;
}
int mid = (l + r) >> ;
build(rt << , l, mid);
build(rt << | , mid + , r);
PushUp(rt);
} void update(int L, int R, int c, int l, int r, int rt)
{
if (L<=l&&r<=R)
{
lazy[rt] = c;
sum[rt] = c * (r - l + ); //从这里可以看出,lazy[]是对该节点以下的所有子节点起作用的,该节点的sum为对应区间总和的实际值,而它的子节点的sum的实际值则取决于lazy
return;
}
pushdown(rt, r - l + ); //如果上面的if语句不成立(未找到要求区间),所以要继续向该节点的左右儿子查询,所以要将该节点的lazy标记下放给该节点的左右儿子
int mid = (l + r) >> ;
if (L <= mid)update(L, R, c, l, mid, rt << );
if (R > mid)update(L, R, c, mid + , r, rt << | );
PushUp(rt); //懒惰标记只能保证递归到该要求的区间时停止,所以依然要更新包含该段区间的所有大区间的值
} int query(int L, int R, int l, int r, int rt)
{
if (L <= l && r <= R)
{
return sum[rt];
}
pushdown(rt, r - l + );
int mid = (l + r) >> ;
int ans = ;
if (L <= mid)ans += query(L, R, l, mid, rt << ); //在该节点左儿子的值
if (R > mid)ans += query(L, R, mid + , r, rt << | );
return ans;
} int main()
{
int t; cin >> t;
for(int ncase = ; ncase <= t;ncase++)
{
int n; scanf("%d", &n);
int m; scanf("%d", &m);
build(, , n);
for (int i = ; i < m; i++)
{
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
update(x, y, z, , n, );
}
printf("Case %d: The total value of the hook is %d.\n", ncase, query(, n, , n, ));
}
return ;
}
2018-07-24
hdu1698 Just a Hook 【区间修改】(模板题)的更多相关文章
- 线段树:Segment Tree(单点修改/区间修改模板) C++
线段树是非常有效的数据结构,可以快速的维护单点修改,区域修改,查询最大值,最小值等功能. 同时,它也很重要.如果有一天比赛,你卡在了一道线段树模板题目上,这就真的尴尬了.不过,随着时代的进步,题目也越 ...
- BZOJ 3223: Tyvj 1729 文艺平衡树-Splay树(区间翻转)模板题
3223: Tyvj 1729 文艺平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 6881 Solved: 4213[Submit][Sta ...
- POJ - 3468 线段树单点查询,单点修改区间查询,区间修改模板(求和)
题意: 给定一个数字n,表示这段区间的总长度.然后输入n个数,然后输入q,然后输入a,b,表示查询a,b,区间和,或者输入c 再输入三个数字a,b,c,更改a,b区间为c 思路: 线段树首先就是递归建 ...
- poj3468 A Simple Problem with Integers(zkw区间修改模板)
此题是一道线段树的裸题,这里只是为了保存我的zkw线段树模板 #include <cstdio> #include <cstring> #include <iostrea ...
- HDU1698 Just a Hook (区间更新)
Just a Hook Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- 石子合并 区间DP模板题
题目链接:https://vjudge.net/problem/51Nod-1021 题意 N堆石子摆成一条线.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石 ...
- P4145——线段树点修改&&模板题
题目 链接 题意:对一个数列进行以下两种操作: 给$[l,r]$中的每个数开平方(下取整) 询问$[l,r]$中各个数的和 解决方法 显然,区间开平方不满足区间可加性,所以对区间中每个数开平方不能通过 ...
- A - Brackets POJ - 2955 (区间DP模板题)
题目链接:https://cn.vjudge.net/contest/276243#problem/A 题目大意:给你一个字符串,让你求出字符串的最长匹配子串. 具体思路:三个for循环暴力,对于一个 ...
- FZU Problem 2171 防守阵地 II (线段树区间更新模板题)
http://acm.fzu.edu.cn/problem.php?pid=2171 成段增减,区间求和.add累加更新的次数. #include <iostream> #include ...
- P1198最大数——线段树点修改&&模板题
题目 题目链接 大意:维护一个数列,有两种操作: 查询操作Q L:查询当前数列中末尾L个数中的最大的数 插入操作A n:将n加上t再对D取模,将所得值插入数列末尾 解决方案 由题意知,只有两种操作 ...
随机推荐
- mysql架构解读~mysql的多源复制
一 场景需求 多源复制版本 5.7,目标主机5.6.21 4个DB机器的某些数据库需要数据汇总进行连表查询 二 进行搭建 1 导出相应的目的库 mysqldump -uuser -ppass ...
- js数组的操作push,pop,shift,unshift
push(args)可以每次压入多个元素,并返回更新后的数组长度. var oldArr=[1,2,3]; alert(oldArr.push(4,[5,6]))–>5(这里只会将[5,6]当做 ...
- C++学习2--坦克大战编写-前置知识
基础班学习的这一个多月里的前三周讲解基础的语法,最后一周需要做坦克大战的项目巩固提高自己掌握的语法知识.这个系列博文主要是为了把学习过程中的知识点总结并记录下来: 开发语言与开发工具:C++,VS20 ...
- 【工具测试】Acunetix 11-登录后扫描的功能
1.概要 在测试的过程中,会给一些只有登录口的测试站点,只有登录后才能访问更多的页面. Acunetix 11的登录后扫描功能摸索了老半天,原来这么神奇.学习了! 2.操作 登录之后 - [Add T ...
- Python基础-封装与扩展、静态方法和类方法
一.封装与扩展 封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码:而外部使用者只知道一个接口(函数),只要接口(函数)名.参数不变,使用者的代码永远无需改变.这就提供一个 ...
- ARMV8 datasheet学习笔记5:异常模型
1.前言 2.异常类型描述 见 ARMV8 datasheet学习笔记4:AArch64系统级体系结构之编程模型(1)-EL/ET/ST 一文 3. 异常处理路由对比 AArch32.AArch64架 ...
- Linux内核驱动--硬件访问I/O【原创】
寄存器与内存 寄存器与内存的区别在哪里呢? 寄存器和RAM的主要不同在于寄存器操作有副作用(side effect或边际效果): 读取某个地址时可能导致该地址内容发生变化,比如很多设备的中断状态寄存器 ...
- __ATTRIBUTE__ 知多少?
GNU C 的一大特色就是__attribute__ 机制.__attribute__ 可以设置函数属性(Function Attribute ).变量属性(Variable Attribute )和 ...
- 详解.NET IL代码(一)
本文主要介绍IL代码,内容大部分来自网上,进行整理合并的. 一.IL简介 为什么要了解IL代码? 如果想学好.NET,IL是必须的基础,IL代码是.NET运行的基础,当我们对运行结果有异议的时候,可以 ...
- SpringMVC中fastjson支持jsonp的实现
前边一篇文章主要说了下前端处理jsonp的方式,这篇主要介绍了后台接收和响应jsonp的一种方式 继承fastjson消息转换器类:com.alibaba.fastjson.support.sprin ...