线段树模板题:
hdu1166,先摆模板:
(1):线段树的构造 void build(int l, int r, int rt);
主要思想是递归构造,如果当前节点记录的区间只有一个值,则直接赋值,否则递归构造左右子树,最后回溯的时候给当前节点赋值
<span style="font-family:Comic Sans MS;">void Build(int l, int r, int rt)
{
if(l == r)
{
scanf("%d", &sum[rt]);
return ;
}
int m = ( l + r )>>1;
Build(lson);
Build(rson);
PushPlus(rt);
}</span>
(2):区间查询int query(int node, int begin, int end, int left, int right);
(其中node为当前查询节点,begin,end为当前节点存储的区间,left,right为此次query所要查询的区间)
主要思想是把所要查询的区间[a,b]划分为线段树上的节点,然后将这些节点代表的区间合并起来得到所需信息
<span style="font-family:Comic Sans MS;">int query(int node, int begin, int end, int left, int right)
{
int p1, p2;
/* 查询区间和要求的区间没有交集 */
if (left > end || right < begin)
return -1;
/* if the current interval is included in */
/* the query interval return segTree[node] */
if (begin >= left && end <= right)
return segTree[node];
/* compute the minimum position in the */
/* left and right part of the interval */
p1 = query(2 * node, begin, (begin + end) / 2, left, right);
p2 = query(2 * node + 1, (begin + end) / 2 + 1, end, left, right);
/* return the expect value */
if (p1 == -1)
return p2;
if (p2 == -1)
return p1;
if (p1 <= p2)
return p1;
return p2;
} </span><span style="font-family:FangSong_GB2312;">
</span>
a:单节点更新
<span style="font-family:Comic Sans MS;">void Updata(int node, int begin, int end, int ind, int add)/*单节点更新*/
{
if( begin == end )
{
segTree[node] += add;
return ;
}
int m = ( left + right ) >> 1;
if(ind <= m)
Updata(node * 2,left, m, ind, add);
else
Updata(node * 2 + 1, m + 1, right, ind, add);
/*回溯更新父节点*/
segTree[node] = min(segTree[node * 2], segTree[node * 2 + 1]);
} </span><span style="font-family: FangSong_GB2312; "> </span>
HDU1166用的就是单节点更新
<span style="font-family:Comic Sans MS;">#include<cstring>
#include<iostream>
#define M 50005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
/*left,right,root,middle*/
int sum[M<<2];
inline void PushPlus(int rt)
{
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void Build(int l, int r, int rt)
{
if(l == r)
{
scanf("%d", &sum[rt]);
return ;
}
int m = ( l + r )>>1;
Build(lson);
Build(rson);
PushPlus(rt);
}
void Updata(int p, int add, int l, int r, int rt)
{
if( l == r )
{
sum[rt] += add;
return ;
}
int m = ( l + r ) >> 1;
if(p <= m)
Updata(p, add, lson);
else
Updata(p, add, rson);
PushPlus(rt);
}
int Query(int L,int R,int l,int r,int rt)
{
if( L <= l && r <= R )
{
return sum[rt];
}
int m = ( l + r ) >> 1;
int ans=0;
if(L<=m )
ans+=Query(L,R,lson);
if(R>m)
ans+=Query(L,R,rson);
return ans;
}
int main()
{
int T, n, a, b;
scanf("%d",&T);
for( int i = 1; i <= T; ++i )
{
printf("Case %d:\n",i);
scanf("%d",&n);
Build(1,n,1);
char op[10];
while( scanf("%s",op) &&op[0]!='E' )
{
scanf("%d %d", &a, &b);
if(op[0] == 'Q')
printf("%d\n",Query(a,b,1,n,1));
else if(op[0] == 'S')
Updata(a,-b,1,n,1);
else
Updata(a,b,1,n,1);
}
}
return 0;
} </span>
要学会使用模板,必须好好的理解算法,至少要明确每个变量的意义,思路清晰了,代码也就不是问题
参考http://blog.csdn.net/metalseed/article/details/8039326