hdu1698 Just a Hook

题意:O(-1)

思路:O(-1)

线段树功能:update:成段替换 (由于只query一次总区间,所以可以直接输出1结点的信息)

题意:给一组棍子染色,不同的颜色有不同的值,执行一系列的区间染色后,问这组棍子的总值是多少。

#include <cstdio>
#include <algorithm>
using namespace std; #define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 111111;
struct Tree{
int value;
int type;
}tree[maxn<<2];
int col[maxn<<2]; void PushUp(int rt) {
tree[rt].value = tree[rt<<1].value + tree[rt<<1|1].value;
}
void PushDown(int rt,int ms) {
if (tree[rt].type) {
tree[rt<<1].type = tree[rt<<1|1].type = tree[rt].type ;
tree[rt<<1].value = (ms - (ms >> 1)) * tree[rt].type;
tree[rt<<1|1].value = (ms >> 1) * tree[rt].type;
tree[rt].type = 0;
}
}
void build(int l,int r,int rt) {
tree[rt].type=0;
tree[rt].value=1;//chushizhi
if (l == r) return ;
int m = (l + r) >> 1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int L,int R,int c,int l,int r,int rt) {
if (L <= l && r <= R) {//标记1 //更新到这就行,不一定更新到最底端
tree[rt].type = c;
tree[rt].value = c * (r - l + 1);
return ;
}
PushDown(rt , r - l + 1);//延迟标记,这时候后推, (标记2)
//比如建了 [1,4] 然后我们第一次的时候是更新[1,2]
// [1,2][3,4] [1,2]的type就是非0,value往上更新;
// [1][2][3][4] 第二次如果还是要更新[1,2] 在标记1直接更新
int m = (l + r) >> 1; // 而如果你是要更新[1,1](必定访问到标记2) 那么先进行标记2 让两儿子的value更新
if (L <= m) update(L , R , c , lson); //记得这时候儿子type被赋值,自己type=0;
if (R > m) update(L , R , c , rson);
PushUp(rt);
}
int main() {
int T , n , m;
scanf("%d",&T);
for (int cas = 1 ; cas <= T ; cas ++) {
scanf("%d%d",&n,&m);
build(1 , n , 1);
while (m --) {
int a , b , c;
scanf("%d%d%d",&a,&b,&c);
update(a , b , c , 1 , n , 1);
}
printf("Case %d: The total value of the hook is %d.\n",cas , tree[1].value);
}
return 0;
}

我觉得这个讲的也挺不错的:

// HDU 1698 Just a Hook 线段树(线段替换)插线插线+ 延时标记
// 延时标记:起一个缓冲的作用,第一次遇到的更新先不更新到底,等下一次更新或者查询的时候再更新到位。
// 因此线段树结构中的区间和 并不是实际值。
// 此处的更新到位是指 本次更新或查询所需的最后一层(因为我查的不是点,而是区间),并非到最底层
// 延时标记下沉的前提:线段树结构中遇到了一个区间完全的包含于待更新区间,即遇到一个待更新区间的子区间
// 注意的是:
// 1.下沉这个标记的时候也要更新区间的实际和,下沉过的标记要及时取消
// 2.递归网上弹准备跳出的时候应该顺便更新区间的实际和,也就是把孩子的两个区间实际和相加
// 3.往左或者往右需要进行深层递归的条件:该区间的子区间与待更新区间存在交集
// 4.对我自己要说的,由于是先更新左区间,因此对右区间的更新不受影响,那么待更新的区间就不需要分割了
// /*test data
1
10
4
1 5 2
5 9 3
1 1 1
10 10 1 out = 23
*/
#include <stdio.h>
#include <string.h>
#include <math.h> const int M = 400001;
struct NODE{
int value;
int left,right; // 其实这两个区间端点都可以不用存起来
int buffer; // 延时标记。
}node[M]; void BuildTree(int i,int left, int right){
node[i].left = left;
node[i].right = right;
node[i].value = node[i].right - node[i].left + 1;
node[i].buffer = 0;
if (node[i].left == node[i].right){
return ;
}
BuildTree(i<<1,left,(left+right)/2);
BuildTree((i<<1)+1,(left+right)/2+1,right);
} int a,b,v; // updata interval = [a,b]
void UpdataTree(int i){ // only revise the buffer
if (a <= node[i].left && node[i].right <= b){ // if find a interval contained goal interval completely
node[i].value = (node[i].right - node[i].left + 1 ) * v;
if (node[i].left != node[i].right) // 末结点不需要延时标记
node[i].buffer = v; // replace
return;
}
if (node[i].buffer){ // if exsit buffer
int l = i << 1;
node[l].buffer = node[l+1].buffer = node[i].buffer; // Make buffer sinking
node[i].buffer = 0;
node[l].value = (node[l].right - node[l].left + 1 ) * node[l].buffer; // 左孩子,利用buffer完成上一次未完成的更新
l++;
node[l].value = (node[l].right - node[l].left + 1 ) * node[l].buffer; // 右孩子,利用buffer完成上一次未完成的更新
}
if (a <= node[i<<1].right) // ***由于先执行的左边,所以待更新区间无需分割,并不影响右边的执行**** ///
UpdataTree(i<<1);
if (b >= node[(i<<1)+1].left)
UpdataTree((i<<1)+1);
// finally, this node will be the sum of the two child
node[i].value = node[i<<1].value + node[(i<<1)+1].value;
} int main(){
freopen("in.txt","r",stdin);
int ncase,d=1;
scanf("%d",&ncase); while(ncase--){
int nn,n_u;
scanf("%d%d",&nn,&n_u);
BuildTree(1,1,nn);
while(n_u--){ // updata
scanf("%d%d%d",&a,&b,&v);
UpdataTree(1); // start from NO.1 interval to updata interval [1,nn] by increase v
}
printf("Case %d: The total value of the hook is %d.\n",d++,node[1].value);
}
return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

线段树---成段更新hdu1698 Just a Hook的更多相关文章

  1. ACM: Copying Data 线段树-成段更新-解题报告

    Copying Data Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Description W ...

  2. Codeforces Round #149 (Div. 2) E. XOR on Segment (线段树成段更新+二进制)

    题目链接:http://codeforces.com/problemset/problem/242/E 给你n个数,m个操作,操作1是查询l到r之间的和,操作2是将l到r之间的每个数xor与x. 这题 ...

  3. POJ 2777 Count Color (线段树成段更新+二进制思维)

    题目链接:http://poj.org/problem?id=2777 题意是有L个单位长的画板,T种颜色,O个操作.画板初始化为颜色1.操作C讲l到r单位之间的颜色变为c,操作P查询l到r单位之间的 ...

  4. hdu 4747【线段树-成段更新】.cpp

    题意: 给出一个有n个数的数列,并定义mex(l, r)表示数列中第l个元素到第r个元素中第一个没有出现的最小非负整数. 求出这个数列中所有mex的值. 思路: 可以看出对于一个数列,mex(r, r ...

  5. HDU1698_Just a Hook(线段树/成段更新)

    解题报告 题意: 原本区间1到n都是1,区间成段改变成一个值,求最后区间1到n的和. 思路: 线段树成段更新,区间去和. #include <iostream> #include < ...

  6. HDU 3577 Fast Arrangement ( 线段树 成段更新 区间最值 区间最大覆盖次数 )

    线段树成段更新+区间最值. 注意某人的乘车区间是[a, b-1],因为他在b站就下车了. #include <cstdio> #include <cstring> #inclu ...

  7. poj 3468 A Simple Problem with Integers 【线段树-成段更新】

    题目:id=3468" target="_blank">poj 3468 A Simple Problem with Integers 题意:给出n个数.两种操作 ...

  8. POJ3468_A Simple Problem with Integers(线段树/成段更新)

    解题报告 题意: 略 思路: 线段树成段更新,区间求和. #include <iostream> #include <cstring> #include <cstdio& ...

  9. poj 3648 线段树成段更新

    线段树成段更新需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候.延迟标记的意思是:这个区间的左右儿子都需要被更新,但是当 ...

随机推荐

  1. c# 在 websocket 中访问 session

    今天的项目需要用到websocket,但是中websocket中无法直接访问session,一访问session就出错,断开连接. 找了老半天百度也没有相关c#的介绍和方法,没办法,找不到现成的代码, ...

  2. IntelliJ IDEA(2018)安装和破解。

    一.下载并安装, IntelliJ IDEA的官网:https://www.jetbrains.com           二.破解. 百度下载一个 JetbrainsCrack-2.6.2.jar ...

  3. MongoDB数据库 : 管道,用户管理,副本集等

    聚合(aggregate): db.集合.aggregate([{管道:{表达式}}]) db.集合.aggregate([ {管道1:{表达式1}}, {管道2:{表达式2}}, ... ...]) ...

  4. JavaScript入门学习(2)--进度条

    <html> <style type="text/css"> #bar{width:0px; height:20px; background:#ee00ff ...

  5. 假期C语言学习笔记4

    函数 经过三个星期的慕课的学习大致上学会了C的一些基本知识,在经过三个星期的C语言课本实践将书上的例题,课后练习实践挨个做了一遍,终于到了函数这一章.时间过的好快呀. 函数分为库函数和自定义函数:有返 ...

  6. 2016-2017-2 20155331 实验二《Java面向对象程序设计》实验报告

    2016-2017-2 20155331 实验二<Java面向对象程序设计>实验报告 实验内容 1.初步掌握单元测试和TDD 2.理解并掌握面向对象三要素:封装.继承.多态 3.初步掌握U ...

  7. 好玩的虚拟机和有趣的Linux系统 ——20155332

    color=#安装虚拟机 学习基于VirtualBox虚拟机安装Ubuntu图文教程在自己笔记本上安装Linux操作系统 我从官网下载了Ubuntu64位操作系统和VMare Workstion虚拟机 ...

  8. POI导出excel文件样式

    需求: 公司业务和银行挂钩,各种形式的数据之间交互性比较强,这就涉及到了存储形式之间的转换 比如数据库数据与excel文件之间的转换 解决: 我目前使用过的是POI转换数据库和文件之间的数据,下边上代 ...

  9. 【转载】图说C++对象模型:对象内存布局详解

    原文: 图说C++对象模型:对象内存布局详解 正文 回到顶部 0.前言 文章较长,而且内容相对来说比较枯燥,希望对C++对象的内存布局.虚表指针.虚基类指针等有深入了解的朋友可以慢慢看.本文的结论都在 ...

  10. 【redis的搭建】centos6.4下搭建redis

    说明:本文内容参考自一些资料,如有雷同,还请见谅. 部分参考: http://blog.csdn.net/su377486/article/details/51803616 http://blog.c ...