线段树(单点更新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 ...
随机推荐
- 【ASP.NET Web API教程】5.1 HTTP消息处理器
原文:[ASP.NET Web API教程]5.1 HTTP消息处理器 注:本文是[ASP.NET Web API系列教程]的一部分,如果您是第一次看本系列教程,请先看前面的内容. 5.1 HTTP ...
- 14.2.4 InnoDB Undo Logs
14.2.4 InnoDB Undo Logs : 一个Undo log (或者成为回滚段) 是一个存储区域 持有被活动事务修改的数据的copy. 如果另外的事务需要看原始的数据(作为一致性读操作的一 ...
- 用Ajax删除的做法
一般程序文件代码 using System;using System.Web;using System.Linq;using System.Data.Linq; public class Shanch ...
- 给c++程序员的一份礼物——常用工具集
给c++程序员的一份礼物——常用工具集 [声明]如需复制.传播,请附上本声明,谢谢.原文出处:http://morningspace.51.net/,moyingzz@etang.com 所谓&quo ...
- Js实现select联动,option从数据库中读取
待要实现的功能:页面有两个select下拉列表,从第一个select中选择后,在第二个select中出现对应的列表选择,再从第二个select中选择后,在一个text中显示对应的信息.两个select ...
- 例3.1 猜猜数据结构 UVa11995
1.标题叙述性说明:点击打开链接 2.解题思路:据来推測一种可能的数据结构,备选答案有"栈,队列.优先队列".结果也可能都不是或者不确定. STL中已经有这三种数据结构了,因此直接 ...
- CDOJ 1221 Ancient Go
题目链接:http://acm.uestc.edu.cn/#/problem/show/1221 题目分类:dfs 代码: #include<bits/stdc++.h> using na ...
- osc搜索引擎框架search-framework,TngouDB,gso,
项目目的:OSChina 实现全文搜索的简单封装框架 License: Public Domain 包含内容: 重建索引工具 -> IndexRebuilder.java 增量构建索引工具 -& ...
- 从零开始学C++之从C到C++(二):引用、内联函数inline、四种类型转换运算符
一.引用 (1).引用是给一个变量起别名 定义引用的一般格式:类型 &引用名 = 变量名: 例如:int a=1; int &b=a;// b是a的别名,因此a和b是同一个单元 注 ...
- java 状态模式 解说演示样例代码
package org.rui.pattern; import junit.framework.*; /** * 为了使同一个方法调用能够产生不同的行为,State 模式在代理(surrogate)的 ...