模板:线段树 & 线段树区间赋值

基础线段树 & 线段树区间赋值
struct SegmentTree{ // 线段树的结构体
	int l, r;
	int dat, lazy;
}t[maxn*4 + 2];
void Build(int p,int l,int r){
	t[p].l = l, t[p].r = r;
	if (l == r) { t[p].dat = a[l]; return; }
	int mid = (l + r) >> 1;
	Build(lson, l, mid); // p*2
	Build(rson, mid+1, r);// p*2 + 1
	t[p].dat = t[lson].dat + t[rson].dat; // 视情况而定
}
void lazytag(int p){
	if(t[p].lazy){
		t[lson].dat += t[p].lazy * (t[lson].r - t[lson].l + 1);
		t[rson].dat += t[p].lazy * (t[rson].r - t[rson].l + 1);
		t[lson].lazy += t[p].lazy;
		t[rson].lazy += t[p].lazy;
		t[p].lazy = 0;// 及时更改标记
	}
}
void Add(int p, int x, int k){//单点修改
	if (t[p].l == t[p].r) { t[p].dat += k; return;}
	int mid = (t[p].l + t[p].r) >> 1;
	if (x <= mid) Add(lson, x, k);
	else if (mid < x) Add(rson, x, k);
	t[p].dat = t[lson].dat + t[rson].dat; // 视情况而定
}
int query(int p,int x, int y){//区间查询
	if(x <= t[p].l && t[p].r <= y) return t[p].dat;
    lazytag(p);
	int mid = (t[p].l + t[p].r) >> 1, val = 0;
	if (x <= mid) val += query(lson, x, y);
	if (mid < y) val += query(rson, x, y);	
	return val;
}
void change(int point, int x, int y, int val){//区间修改
	if (x <= t[point].left && t[point].right <= y){
		t[point].data += (ll)val * (t[point].right-t[point].left+1);
        t[point].lazy += val;//打上懒标记
        return;
	}
	lazytag(point);
	int mid = (t[point].left + t[point].right) / 2; //熟悉的二分 
	if (x <= mid) change(point*2, x, y, val); 	//x在左边 
	if (mid < y) change(point*2+1, x, y, val); //x在右边 
	t[point].data = t[point*2].data + t[point*2+1].data;//看情况
} 
// 区间赋值 01的
void push_up(int p){
	t[p].data = t[p*2].data + t[p*2+1].data;
}
void Build(int p,int l, int r){//建树存区间1的个数
	t[p].left  = l, t[p].right = r;
	if(r == l){
        t[p].data = arr[l];
		return;
	}
	int mid = (l + r) >> 1;
	Build(p*2, l, mid);
	Build(p*2+1, mid+1, r);
	push_up(p);
}
void push_down(int p){
    if(t[p].lazy != -1){//如果懒标记不为-1,就将其下传,修改左右儿子维护的值
    	t[p*2].lazy = t[p*2+1].lazy = t[p].lazy;//子节点继承父节点的lazy
    	int mid = (t[p].left + t[p].right) >> 1;
    	t[p*2].data = t[p].lazy*(mid - t[p].left + 1);
    	t[p*2+1].data = t[p].lazy*(t[p].right - mid );
    	t[p].data = t[p].lazy * (t[p].right - t[p].left + 1);
        t[p].lazy = -1;//下传之后将该节点的懒标记清0
        //cout<<"t[p].left  : "<<t[p].left<< "  t[p].right : "<<t[p].right<<" t[p].data : "<<t[p].data <<endl;
    }
}
void dis(int p, int l, int r){
    if(t[p].left == t[p].right){
        cout<<t[p].data;
        return ;
    }
    push_down(p);
    int mid = ( t[p].left + t[p].right) >> 1;
    dis(p*2,l , mid);
    dis(p*2+1, mid +1,r);
}
void up_date(int p,int l,int r,int v){
    if(l > r || r > SIZE) return;
    if(t[p].left ==l&&t[p].right==r){
        t[p].lazy = v;
        t[p].data = v * (r - l + 1);
        return ;
    }
    push_down(p);
    int mid=(t[p].left+t[p].right) >> 1;
    if(r<=mid){
        up_date(p*2,l,r,v);
    }
    else if(l>mid){
        up_date(p*2+1,l,r,v);
    }
    else{
        up_date(p*2,l,mid,v);
        up_date(p*2+1,mid+1,r,v);
    }
    push_up(p);
}
int ask(int p, int x, int y){
	if(x <= t[p].left && t[p].right <= y)
        return t[p].data;
	push_down(p);//下传懒标记,并查询左右儿子
	int mid = (t[p].left + t[p].right) / 2;
	int val = 0;
	if (x <= mid)
		val += ask(p*2, x, y);
	if(mid < y)
		val += ask(p*2+1, x, y);
	return val;
}
void Init(){
    for(int i=1;i<=SIZE*4;i++)
        t[i].lazy = -1;
}
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

TUStarry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值