您的位置:首页 > 其它

线段树(简单模板)

2017-10-02 19:08 323 查看
#define LL long long
struct hh
{
int l,r,ls,rs;//l,r为边界,ls,rs为左右儿子的编号
LL date;//权值
}t[800000];
LL n,m,num=0,x,y,v,pd,a[200010],add[200010];//add为标记要增大的值的数组
void pushup(int i)//重新求权值
{
t[i].date=t[t[i].ls].date+t[t[i].rs].date;
}
void build(int l,int r)//建树
{
num++;
add[num]=0;
t[num].date =0;
int node=num;
t[node].l=l;
t[node].r=r;
if(l!=r)
{
t[node].ls=num+1;
build(l,(l+r)/2);

t[node].rs=num+1;
build(((l+r)/2)+1,r);

pushup(node);

}
else if(l==r)
{
t[node].date=a[l];
}
}
void pushdown(int i)//把标记传下去
{
if(add[i]!=0) //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
{
int ls=t[i].ls;int rs=t[i].rs;
add[ls]+=add[i];add[rs]+=add[i];
t[ls].date+=add[i]*(t[ls].r-t[ls].l+1);
t[rs].date+=add[i]*(t[rs].r-t[rs].l+1);
add[i]=0;
}
}
void update(int i,int l,int r,int v)//更新函数
{
if(t[i].l==l&&t[i].r==r)
{
add[i]+=v;
t[i].date+=add[i]*(r-l+1);
return ;
}
if(t[i].l==t[i].r) return ;
pushdown(i);
int z=t[i].l+t[i].r;
z/=2;
if(r<=z) update (t[i].ls,l,r,v);
else if(l>z) update(t[i].rs,l,r,v);
else
{
update(t[i].ls,l,z,v);
update(t[i].rs,z+1,r,v);
}
pushup(i);
}
LL query(int i,int l,int r)//求和函数
{
if(t[i].l==l&&t[i].r==r)
return t[i].date ;
pushdown(i);
int z=(t[i].l+t[i].r)/2;
if(r<=z) return query(t[i].ls,l,r);
else if(l>z) return query(t[i].rs,l,r);
else
{
return query(t[i].ls,l,z)+query(t[i].rs,z+1,r);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: