数据结构——线段树之二(C++)

源代码:

#include<cstdio>
int n,num(0),h[100001];
struct treetype
{
int left,right,lefts,rights,sum,sign;
}i[200020];
void x1(int t1,int t2) //建树。
{
int t=++num;
i[t].left=t1;
i[t].right=t2;
if (t1!=t2-1)
{
i[t].lefts=num+1;
x1(t1,(t1+t2)/2);
i[t].rights=num+1;
x1((t1+t2)/2,t2);
i[t].sum=i[i[t].lefts].sum+i[i[t].rights].sum;
}
else
i[t].sum=h[t1];
}
void lazy(int t) //利用省劲的懒惰算法,向下加深一层。
{
i[i[t].lefts].sum+=i[t].sign*(i[i[t].lefts].right-i[i[t].lefts].left);
i[i[t].rights].sum+=i[t].sign*(i[i[t].rights].right-i[i[t].rights].left);
i[i[t].lefts].sign+=i[t].sign;
i[i[t].rights].sign+=i[t].sign;
i[t].sign=0;
}
void x2(int t,int x,int y,int z)
{
if (x<=i[t].left&&y>=i[t].right)
{
i[t].sum+=z*(i[t].right-i[t].left);
i[t].sign+=z; //可能还留有处理过的标记,故应进行叠加。
}
else
{
if (i[t].sign) //为继续向下搜索,进行提前准备。
lazy(t);
if (x<(i[t].left+i[t].right)/2)
x2(i[t].lefts,x,y,z);
if (y>(i[t].left+i[t].right)/2)
x2(i[t].rights,x,y,z);
i[t].sum=i[i[t].lefts].sum+i[i[t].rights].sum;
}
}
int x3(int t,int x,int y) //求和。
{
if (x<=i[t].left&&y>=i[t].right)
return i[t].sum;
if (i[t].sign) //同理于上,为继续向下搜索,进行提前准备。
lazy(t);
int ans(0);
if (x<(i[t].left+i[t].right)/2)
ans+=x3(i[t].lefts,x,y);
if (y>(i[t].left+i[t].right)/2)
ans+=x3(i[t].rights,x,y);
return ans;
}
int main()
{
scanf("%d",&n);
for (int a=1;a<=n;a++)
scanf("%d",&h[a]);
x1(1,n+1);
scanf("%d",&n);
for (int a=1;a<=n;a++)
{
int t;
scanf("%d",&t);
if (t==1)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z); //进行区间范围的修改。
x2(1,x,y+1,z); //以半闭半开区间形式进行处理。
}
else
{
int x,y;
scanf("%d%d",&x,&y);
printf("%d\n",x3(1,x,y+1)); //同理于上,以半闭半开区间形式进行处理。
}
}
return 0;
}

时间: 2024-08-10 09:22:22

数据结构——线段树之二(C++)的相关文章

Chapter 3. 数据结构 线段树

Chapter 3. 数据结构 线段树 Sylvia's I.单点修改,区间查询. 模板: //单点修改 区间求和 //1操作 单点修改//2操作 区间求和 #include<cstdio> #include<iostream> using namespace std; #define MAXN 500005 int sum[MAXN<<2]; int n,m; void PushUp(int rt){//求和 sum[rt]=sum[rt<<1]+sum[

HDU 4902 Nice boat(数据结构-线段树)

Nice boat Problem Description There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his people. Now he is just like a boy in love and c

hdu 2795 线段树(二维问题一维化)

Billboard Time Limit: 20000/8000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 10961    Accepted Submission(s): 4863 Problem Description At the entrance to the university, there is a huge rectangular billboard of s

HDU 1394 Minimum Inversion Number (数据结构-线段树)

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 9514    Accepted Submission(s): 5860 Problem Description The inversion number of a given number sequence a1, a2, ..., an

论线段树:二

<论线段树> ——线段树精细讲解第二篇   ——Yeasion_Nein出品 ><论线段树:一> ><论线段树:二> 在上一节中,我们大概了解了线段树的运算机制以及基本的代码运行 ,在这一节,我们主要针对一个例题进行更深层次的讲解. 首先来看一道题.(题目原链接:线段树2 [模板]线段树 2 题目描述 如题,已知一个数列,你需要进行下面三种操作: 1.将某区间每一个数乘上x 2.将某区间每一个数加上x 3.求出某区间每一个数的和 输入输出格式 输入格式: 第

数据结构——线段树

线段树是一种基于分治思想的类似于二叉树的数据结构,一般用于数组的信息统计,相比于树状数组,线段树有着更广阔的应用空间,但是相对的其代码量长,且常数大 一. 首先我们来讲线段树的建树过程,请看下图: 这张图就是线段树的存储结构,我们从最长的区间开始依次分成两部分,每一部分都有一个需要维护的权,建树过程比较简单,代码如下: inline void build(int l,int r,int rt) //l表示当前的左端点,r表示右端点,rt是当前区间的编号 { if(l == r) //当左右端点相

线段树(二)

转自:http://blog.csdn.net/liujian20150808/article/details/51137749 1.线段树的定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b].因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度. 举例描述: 因此有了以上对线段树的定

spoj GSS线段树以及二维树状数组合集

T1 维护lmax 向左延伸的最大值,rmax同理,sum区间和,ans答案. 转移见operator + #include<bits/stdc++.h> #define mid (l+(r-l)/2) #define ls (rt<<1) #define rs (rt<<1|1) #define int long long using namespace std; const int N =(int)1e5+10; struct TREE { int lef,rig,

数据结构---线段树

线段树 转载请注明出处,谢谢!http://blog.csdn.net/metalseed/article/details/8039326  持续更新中···   一:线段树基本概念 1:概述 线段树,类似区间树,是一个完全二叉树,它在各个节点保存一条线段(数组中的一段子数组),主要用于高效解决连续区间的动态查询问题,由于二叉结构的特性,它基本能保持每个操作的复杂度为O(lgN)! 性质:父亲的区间是[a,b],(c=(a+b)/2)左儿子的区间是[a,c],右儿子的区间是[c+1,b],线段树