题目

给定一组数,要求进行若干次操作,这些操作可以分为两种类型: 
(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. gulp 建立一个简单的自动化

    前端项目需要的功能: 1.图片(压缩图片支持jpg.png.gif) 2.样式 (支持sass 同时支持合并.压缩.重命名) 3.javascript (检查.合并.压缩.重命名) 4.html (压 ...

  2. jquery uploadify上传插件兼容火狐问题

    jquery uploadify长传插件兼容火狐问题.因为现在火狐以不在默认安装flash插件.所以uploadify的flash版就需要安装flash插件.还可以成功. 可以到哪里下载安装:http ...

  3. CALayer的分析

    转载地址:  http://my.oschina.net/u/2340880/blog/536048 iOS开发CoreAnimation解读之二——对CALayer的分析 一.UIView中的CAL ...

  4. SqlSever基础 rtrim与ltrim嵌套使用 除去字符串左右两边的空格

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

  5. 02.iOS开发网络篇—HTTP协议

    iOS开发网络篇—HTTP协议 说明:apache tomcat服务器必须占用8080端口 一.URL 1.基本介绍 URL的全称是Uniform Resource Locator(统一资源定位符) ...

  6. [POJ1830]开关问题(高斯消元,异或方程组)

    题目链接:http://poj.org/problem?id=1830 题意:中文题面,求的是方案数. 首先可以知道, 如果方案数不止一个的话,说明矩阵行列式值为0,即存在自由变元,由于变量只有两种状 ...

  7. JAVA排序--[选择排序]

    package com.array; public class Sort_Select { /** * 项目名称:选择排序 ; * 项目要求:用JAVA对数组进行排序,并运用选择排序算法; * 作者: ...

  8. POJ 2376 Cleaning Shifts(轮班打扫)

    POJ 2376 Cleaning Shifts(轮班打扫) Time Limit: 1000MS   Memory Limit: 65536K [Description] [题目描述] Farmer ...

  9. FZU 2218 Simple String Problem(简单字符串问题)

    Description 题目描述 Recently, you have found your interest in string theory. Here is an interesting que ...

  10. hdu 2196 Computer 树的直径

    Computer Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem ...