线段树(单点更新and成段更新)
线段树需要的空间。
区间为1-->n
假设是一棵完全二叉树,且树高为i。
完全二叉树性质:第i层最多有2^(i-1)个结点。
那么 2^(i-1) = n; i = log2(n) + 1;
共有 2^i - 1 个结点, 即 2^(log2(n) + 1) - 1个结点
即2 * 2^log2(n) - 1 = 2 * n - 1
但这是建立树是完全二叉树的情况下。

但是如图所示,树可能不是完全二叉树,最下面一层的结点个数>n, 我们以2n来来计算,那么就需要4*n-1的空间。
http://acm.hdu.edu.cn/showproblem.php?pid=1166
单点更新
#include <stdio.h>
#include <string.h>
const int N = ;
int a[N*],ans;
void swap(int &a, int &b)
{
int t = a;
a = b;
b = t;
}
void build(int rt, int l, int r)
{
if(l==r)
{
scanf("%d",&a[rt]);
return;
}
int mid = (l + r) >> ;
build(rt<<,l,mid);
build(rt<<|,mid+,r);
a[rt] = a[rt<<] + a[rt<<|];
} void query(int rt, int L, int R, int l, int r)
{
if(L==l && R==r)
{
ans += a[rt];
return;
}
int mid = (l + r) >> ;
if(R<=mid)
query(rt<<,L,R,l,mid);
else if(L>mid)
query(rt<<|,L,R,mid+,r);
else
{
query(rt<<,L,mid,l,mid);
query(rt<<|,mid+,R,mid+,r);
}
}
void update(int rt, int val, int pos, int l, int r)
{
if(l == r)
{
a[rt] += val;
return ;
}
int mid = (l + r) >> ;
if(pos <= mid)
update(rt<<,val,pos,l,mid);
else
update(rt<<|,val,pos,mid+,r);
a[rt] = a[rt<<] + a[rt<<|];
}
int main()
{
int t,n,i,j,tCase;
char str[];
scanf("%d",&t);
for(tCase=; tCase<=t; ++tCase)
{
memset(a,,sizeof(a));
scanf("%d",&n);
build(,,n);
printf("Case %d:\n",tCase);
while(true)
{
scanf("%s",str);
if(str[]=='E')
break;
scanf("%d%d",&i,&j);
if(str[]=='Q')
{
ans = ;
if(i > j)
swap(i,j);
query(,i,j,,n);
printf("%d\n",ans);
}
else if(str[]=='A')
{
update(,j,i,,n);
}
else
update(,-j,i,,n);
}
}
return ;
}
http://acm.hdu.edu.cn/showproblem.php?pid=1698
成段更新, 要用到懒惰标记,每次更改区间时,不会更新到叶子结点,而是标记,等有需要了才去更新
#include <stdio.h>
#include <string.h>
const int N = + ;
struct node
{
int sum;
int tag;
}a[N*];
void pushUp(int rt)
{
a[rt].sum = a[rt<<].sum + a[rt<<|].sum;
}
void pushDown(int rt, int m)
{
if(a[rt].tag != )
{
a[rt<<].tag = a[rt<<|].tag = a[rt].tag;
a[rt<<].sum = (m-(m>>)) * a[rt].tag;
a[rt<<|].sum = (m>>) * a[rt].tag;
a[rt].tag = ;
}
}
void build(int rt, int l, int r)
{
a[rt].tag = ;
if(l==r)
{
a[rt].sum = ;
return ;
}
int mid = (l + r) >> ;
build(rt<<,l,mid);
build(rt<<|,mid+,r);
pushUp(rt);
}
void update(int rt, int L, int R, int val, int l, int r)
{
if(L<=l && r<=R)
{
a[rt].sum = (r-l+)*val;
a[rt].tag = val;
return;
}
pushDown(rt,r-l+);
int mid = (l + r) >> ;
if(L<=mid) update(rt<<,L,R,val,l,mid);
if(R>mid) update(rt<<|,L,R,val,mid+,r);
pushUp(rt);
} int main()
{
int t,tCase,n,i,x,y,z,q;
scanf("%d",&t);
for(tCase=; tCase<=t; ++tCase)
{
scanf("%d",&n);
build(,,n);
scanf("%d",&q);
for(i=; i<q; ++i)
{
scanf("%d%d%d",&x,&y,&z);
update(,x,y,z,,n);
}
printf("Case %d: The total value of the hook is %d.\n",tCase,a[].sum);
}
return ;
}
线段树(单点更新and成段更新)的更多相关文章
- 线段树(多维+双成段更新) UVA 11992 Fast Matrix Operations
题目传送门 题意:训练指南P207 分析:因为矩阵不超过20行,所以可以建20条线段的线段树,支持两个区间更新以及区间查询. #include <bits/stdc++.h> using ...
- POJ 2155 Matrix (二维线段树入门,成段更新,单点查询 / 二维树状数组,区间更新,单点查询)
题意: 有一个n*n的矩阵,初始化全部为0.有2中操作: 1.给一个子矩阵,将这个子矩阵里面所有的0变成1,1变成0:2.询问某点的值 方法一:二维线段树 参考链接: http://blog.csdn ...
- HDU 1754 I Hate It 线段树(单点更新,成段查询)
题目链接: hdu: http://acm.hdu.edu.cn/showproblem.php?pid=1754 题解: 单点更新,成段查询. 代码: #include<iostream> ...
- ACM: Copying Data 线段树-成段更新-解题报告
Copying Data Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%I64d & %I64u Description W ...
- HDU 1698 Just a Hook(线段树成段更新)
Just a Hook Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- Problem 1007 幸运数 线段树成段更新
题目链接: 题目 Problem 1007 幸运数 Time Limit: 2000 mSec Memory Limit : 131072 KB 问题描述 皮特的幸运数是2和5.只由幸运数字2和5组成 ...
- 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. 这题 ...
- POJ 2777 Count Color (线段树成段更新+二进制思维)
题目链接:http://poj.org/problem?id=2777 题意是有L个单位长的画板,T种颜色,O个操作.画板初始化为颜色1.操作C讲l到r单位之间的颜色变为c,操作P查询l到r单位之间的 ...
- Codeforces295A - Greg and Array(线段树的成段更新)
题目大意 给定一个序列a[1],a[2]--a[n] 接下来给出m种操作,每种操作是以下形式的: l r d 表示把区间[l,r]内的每一个数都加上一个值d 之后有k个操作,每个操作是以下形式的: x ...
随机推荐
- JSP中两种include的区别
首先说明这两种都是什么: <%@ include file=”relativeURI”%> 可以叫作静态include(静态包含),是jsp指令中的一种,(JSP指令控制JSP编译器如何去 ...
- android apk反编译
★反编译所需工具 1.AXMLPrinter.jar 2.d2j-dex2jar.bat 3.查看Jar包的GUI工具 ★功能实现 ◇解压缩 apk文件其实就是一个MIME为zip的压缩包,可以用wi ...
- RSA密码系统 基于大数环境编写 密码学课程设计
RSA密码系统的实现 1.问题描述 RSA密码系统可具体描述为:取两个大素数p和q,令n=pq,N=(p-1)(q-1),随机选择整数d,满足gcd(d,N)=1,ed=1 modN. 公开密钥:k1 ...
- ZipHelper 压缩和解压帮助类
ZipHelper 压缩和解压帮助类 关于本文档的说明 本文档基于ICSharpCode.SharpZipLib.dll的封装,常用的解压和压缩方法都已经涵盖在内,都是经过项目实战积累下来的 欢迎传播 ...
- Delphi数据类型转换(有几个字符串函数没见过,比如StringToWideChar和WideCharToString)
DateTimeToFileDate 函数 将DELPHI的日期格式转换为DOS的日期格式 DateTimeT ...
- 为Delphi程序增加UAC功能(每个步骤都很详细)
相关资料:http://bbs.csdn.net/topics/320071356# 操作方法: 在Source\VCL目录下应该有这样两个文件sample.manifest和WindowsXP.rc ...
- java 状态模式 解说演示样例代码
package org.rui.pattern; import junit.framework.*; /** * 为了使同一个方法调用能够产生不同的行为,State 模式在代理(surrogate)的 ...
- MySQL多表查询之外键、表连接、子查询、索引
MySQL多表查询之外键.表连接.子查询.索引 一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复的,不允许为 ...
- haskell,lisp,erlang你们更喜欢哪个?
haskell,lisp,erlang你们更喜欢哪个? haskell,lisp,erlang你们更喜欢哪个?
- 超人学院Hadoop大数据技术资源分享
超人学院Hadoop大数据技术资源分享 http://bbs.superwu.cn/forum.php?mod=viewthread&tid=807&fromuid=645 很多其它精 ...