线段树模板

#include "iostream"
#include "cstdio"
#include "cstdlib"
#include "cmath"
#include "cstring"
#include "algorithm"
using namespace std;
#define MAXN 131072
#define LSON rt<<1
#define RSON rt<<1|1
#define DATA(x) tree[x].data
#define LSIDE(x) tree[x].l
#define RSIDE(x) tree[x].r
#define SIGN(x) tree[x].c
#define WIDTH(x) (RSIDE(x)-LSIDE(x)+1)
struct Node
{        //线段树结点结构体     
long long data,c;    
int l,r;
}tree[MAXN<<1];
void PushUp(int rt)
{    
DATA(rt)=DATA(LSON)+DATA(RSON); //用儿子结点更新当前结点 1 步 
}
void PushDown(int rt)
{//延迟标志下传,并更新子结点 data 6 步     
if(!SIGN(rt) || LSIDE(rt)==RSIDE(rt))return;//两种情况不用下传     
SIGN(LSON)+=SIGN(rt);                       //更新左子节点标志    
DATA(LSON)+=SIGN(rt)*WIDTH(LSON); //更新左子节点 data
SIGN(RSON)+=SIGN(rt);                       //更新右子节点标志    
DATA(RSON)+=SIGN(rt)*WIDTH(RSON);           //更新右子节点 data    
SIGN(rt)=0;//当前结点标志清零 
}
void BuildTree(int l,int r,int rt)
{ //建线段树,并读叶节点数据 6 步     
tree[rt].l=l;
tree[rt].r=r;     //记录结点覆盖区域     
if(l==r)
{                       //如果是叶结点,读取数据并返回         
scanf("%I64d",&tree[rt].data);        
return;    
}    
int m=l+r>>1;                   //计算中点     
BuildTree(l,m,LSON);            //递归左子节点     
BuildTree(m+1,r,RSON);          //递归右子节点     
PushUp(rt);                     //更新当前 data  }  
void Update(int l,int r,long long c,int rt)
{//区间更新 data 6 步     
if(l<=LSIDE(rt) && RSIDE(rt)<=r)
{//结点被覆盖,更新标志和 data         
SIGN(rt)+=c;        
DATA(rt)+=c*WIDTH(rt);        
return;    
}    
PushDown(rt);                   //标志下传     
int m=LSIDE(rt)+RSIDE(rt)>>1;   //计算中点     
if(l<=m)Update(l,r,c,LSON);     //左界小于中点,递归左子     
if(m<r)Update(l,r,c,RSON);      //右界大于中点,递归右子    
PushUp(rt);                     //更新当前 data 
}
long long Query(int l,int r,int rt)
{//区间查询      7 步     
if(l<=LSIDE(rt) && RSIDE(rt)<=r)//结点被覆盖,返回 data         
return DATA(rt);    
PushDown(rt);                   //标志下传     
int m=LSIDE(rt)+RSIDE(rt)>>1;   //计算中点     
long long ans=0;    
if(l<=m)ans+=Query(l,r,LSON);   //左界小于中点,递归左子     
if(m<r) ans+=Query(l,r,RSON);   //右界大于中点,递归右子     
return ans;                     //返回结果 
}
int main()
{    
freopen("mecha.in","r",stdin);    
freopen("mecha.out","w",stdout);    
int n,m;    
while(scanf("%d%d",&n,&m))
{        
BuildTree(1,n,1);        
char a[10];        
int x,y;
long long z;        
while(m--)
{            
scanf("%s",a);            
if(!strcmp(a,"Q"))
{                
scanf("%d%d",&x,&y);                
printf("%I64d\n",Query(x,y,1));
continue;            
}            
if(!strcmp(a,"C"))
{                
scanf("%d%d%I64d",&x,&y,&z);                
Update(x,y,z,1);
continue;            
}        
}    
}    
return 0;

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值