题目

给定一组数,要求进行若干次操作,这些操作可以分为两种类型: 
(1) CMD 1 beg end value 将数组中下标在[beg, end] 区间内数字都变为value 
(2) CMD 2 beg end 求出数组中下标在[beg ,end]区间中的所有数字的和

分析

树状数组在区间查询和单点修改情况下效率较线段树高一些,而无法像线段树一样在O(logN)的时间内完成区间修改。因此使用线段树解决。使用线段树主要的是定义好线段树节点的状态。(如代码中注释所说,状态一定要明确,且容易计算!)

实现

#include<iostream>
#include<string.h>
#include<iostream>
#include<queue>
#include<cmath>
#include<unordered_map>
#include<unordered_set>
#include<string>
#include<vector>
using namespace std;
const int inf = 1 << 29;
const int kMax = 100005;
struct Node{
int beg;
int end;
int val;
//若val为非零值,表示当前时刻,节点所代表的区间内所有的值同时被修改为val;
//如果为0,一种情况是该节点代表区间内的值同时被修改为val,
//一种情况是:该区间内的值没有被同时修改为val(可能从没被修改过,或者之前被同时修改过,但是后来又被修改了其中一部分) int sum; //当前时刻,区间内所有数字的和。这个值就是当前时刻的值,不需要参考value
Node(){
val = sum = 0;
}
};
Node gNodes[4 * kMax];
int weight[kMax];
void BuildTree(int node, int beg, int end){
gNodes[node].beg = beg;
gNodes[node].end = end;
if (beg == end){
gNodes[node].val = gNodes[node].sum = weight[beg]; //初始化
return;
}
int left = 2 * node + 1, right = 2 * node + 2;
int mid = (beg + end) / 2;
BuildTree(left, beg, mid);
BuildTree(right, mid + 1, end);
gNodes[node].sum = gNodes[left].sum + gNodes[right].sum; }
//从上向下更新
void PushDown(int node){
if (gNodes[node].beg == gNodes[node].end){
//叶子节点处的更新,注意,由于 线段树的节点中的 sum被定义为当前时刻的真实的和。那么,
//当叶子节点被修改为了value时,同时将sum给计算出来
gNodes[node].sum = gNodes[node].val;
return;
} int left = 2 * node + 1, right = 2 * node + 2;
if (gNodes[node].val){
//注意,由于 线段树的节点中的 sum被定义为当前时刻的真实的和。那么,每当pushdown,子节点的value被修改时,
//也需要同时将 sum给计算出来!
int value = gNodes[node].val;
gNodes[left].val = gNodes[right].val = value;
gNodes[left].sum = (gNodes[left].end - gNodes[left].beg + 1)*value;
gNodes[right].sum = (gNodes[right].end - gNodes[right].beg + 1)*value;
}
gNodes[node].val = 0;
} //从下向上更新
void PushUp(int node){
if (gNodes[node].beg == gNodes[node].end){
gNodes[node].sum = gNodes[node].val;
return;
} int left = 2 * node + 1, right = 2 * node + 2;
gNodes[node].sum = gNodes[left].sum + gNodes[right].sum;
} void Update(int node, int beg, int end, int value){
if (beg == gNodes[node].beg && end == gNodes[node].end){
//对区间进行更新,节点的val 更新为value不用说了。注意由于我们定义的 节点中的sum为当前时刻的真实的和,因此
//需要实时的计算出来
gNodes[node].val = value;
gNodes[node].sum = gNodes[node].val*(gNodes[node].end - gNodes[node].beg + 1);
return;
}
if (beg > end)
return;
//查询区间和线段树节点代表的区间不同,则进行区间分解。 需要先将父节点的信息传递给子节点
PushDown(node);
int left = 2 * node + 1, right = 2 * node + 2;
int mid = (gNodes[node].beg + gNodes[node].end) / 2;
if (mid >= end){
Update(left, beg, end, value);
}
else if(mid < beg){
Update(right, beg, end, value);
}
else{
Update(left, beg, mid, value);
Update(right, mid + 1, end, value);
}
//线段树子节点更新完之后,需要更新父节点的 sum 信息
PushUp(node);
} int Query(int node, int beg, int end){
if (gNodes[node].beg == beg && gNodes[node].end == end){
return gNodes[node].sum;
}
if (beg > end)
return 0;
PushDown(node);
int left = 2 * node + 1, right = 2 * node + 2;
int mid = (gNodes[node].beg + gNodes[node].end) / 2;
if (mid >= end){
return Query(left, beg, end);
}
else if (mid < beg){
return Query(right, beg, end);
}
else{
int left_sum = Query(left, beg, mid);
int right_sum = Query(right, mid + 1, end);
return left_sum + right_sum;
}
}
int main(){
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++){
scanf("%d", &weight[i]);
}
BuildTree(0, 0, n - 1);
scanf("%d", &n);
int cmd, beg, end, value;
for (int i = 0; i < n; i++){
scanf("%d", &cmd);
if (cmd == 0){
scanf("%d %d", &beg, &end);
int result = Query(0, beg - 1, end - 1);
printf("%d\n", result);
}
else{
scanf("%d %d %d", &beg, &end, &value);
Update(0, beg - 1, end-1, value);
}
}
return 0;
}

hiho_1078_线段树区间修改的更多相关文章

  1. Codeforces Round #442 (Div. 2) E Danil and a Part-time Job (dfs序加上一个线段树区间修改查询)

    题意: 给出一个具有N个点的树,现在给出两种操作: 1.get x,表示询问以x作为根的子树中,1的个数. 2.pow x,表示将以x作为根的子树全部翻转(0变1,1变0). 思路:dfs序加上一个线 ...

  2. 题解报告:hdu 1698 Just a Hook(线段树区间修改+lazy懒标记的运用)

    Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing for m ...

  3. poj 2528 线段树区间修改+离散化

    Mayor's posters POJ 2528 传送门 线段树区间修改加离散化 #include <cstdio> #include <iostream> #include ...

  4. E - Just a Hook HDU - 1698 线段树区间修改区间和模版题

    题意  给出一段初始化全为1的区间  后面可以一段一段更改成 1 或 2 或3 问最后整段区间的和是多少 思路:标准线段树区间和模版题 #include<cstdio> #include& ...

  5. HDU 4027 Can you answer these queries? (线段树区间修改查询)

    描述 A lot of battleships of evil are arranged in a line before the battle. Our commander decides to u ...

  6. poj2528 Mayor's posters(线段树区间修改+特殊离散化)

    Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral electio ...

  7. HDU - 1698 线段树区间修改,区间查询

    这就是很简单的基本的线段树的基本操作,区间修改,区间查询,对区间内部信息打上laze标记,然后维护即可. 我自己做的时候太傻逼了...把区间修改写错了,对给定区间进行修改的时候,mid取的是节点的左右 ...

  8. HDU - 3974 Assign the task (线段树区间修改+构建模型)

    https://cn.vjudge.net/problem/HDU-3974 题意 有一棵树,给一个结点分配任务时,其子树的所有结点都能接受到此任务.有两个操作,C x表示查询x结点此时任务编号,T ...

  9. SPOJ GSS2 - Can you answer these queries II(线段树 区间修改+区间查询)(后缀和)

    GSS2 - Can you answer these queries II #tree Being a completist and a simplist, kid Yang Zhe cannot ...

随机推荐

  1. Adam 演示demo内容整理

    在这个6个多G的演示demo中,还是发现了不少东西. 这篇文章八卦向的东西比较多,不过支持abc格式的话,做Cutscene一下子多了很多可以用的东西. 1.在插件目录下发现了ABC格式的导入dll. ...

  2. c++中两种常量方法的比较

    [c++]在C++中定义常量的两种方法的比较   常量是定以后,在程序运行中不能被改变的标识符.C++中定义常量可以用#define .const 这两种方法.例如: #define PRICE 10 ...

  3. 多条件查询(php+mysql) 租房子例子

    <body> <?php //多条件 $tiaojian2= " 2=2 "; $attr2 = ""; //判断区域 if(!empty($ ...

  4. 批量清除.svn 或 _svn

    Windows Registry Editor Version 5.00[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Folder\shell\DeleteSVN]@=&q ...

  5. Jnotify文件监控的用法以及Jar文件导入的方法

    简介Jnotiy, 支持动态监控(支持级联监控)文件夹和文件的jar包.在linux中,调用linux底层的jnotify服务.在windows中,需要添加附件的dll文件. 因为通用的Maven仓库 ...

  6. zookeeper系列之四—coordinate

    http://zookeeper.apache.org/doc/trunk/zookeeperProgrammers.html

  7. SqlSever基础 union 联合查询,厉害的并集 重复项只显示一个 两个查询结果并在一起后排序

    镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...

  8. 我的android学习经历17

    tomcat的下载安装 1.下载tomcat 在百度中输入tomcat可以直接出现他的英文官网 http://tomcat.apache.org/ 进去以后选择与你的java版本相匹配的tomcat ...

  9. 【leetcode❤python】237. Delete Node in a Linked List

    #-*- coding: UTF-8 -*- # Definition for singly-linked list.# class ListNode(object):#     def __init ...

  10. UVALive 6508 Permutation Graphs

    Permutation Graphs Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit ...