线段树区间更新hdu1698

本文介绍了两种段式更新树的实现方法:一种使用sum存放每个点的值,并通过标记父亲节点进行区间更新;另一种采用lazy标志位,在区间更新时设置标志,并在查询涉及的区间时更新子节点值。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一种是sum存放每个点的值,然后区间更新,把需要更新的父亲的sum设为-1,代表此区间有被更新过,就不由挪动子节点了。

vj上跑的时间这个快一点。

另一种lazy标志位,区间更新时,把lazy标志位设为1,当查找的区间含lazy过的,就变更子节点位原来的值,所以需要一个tag记录原来的值。

</pre><pre name="code" class="cpp">#include<bits/stdc++.h>
using namespace std;
#define N 100100

struct {
    int sum;
    int left,right;
}b[N*4];
void build(int left,int right,int i){
    int mid;
    b[i].left=left;b[i].right=right;b[i].sum=1;
    if(left==right) {
        b[i].sum=1;
        return ;
    }
    mid = (left+right)/2;
    build(left,mid,2*i);
    build(mid+1,right,2*i+1);
}
void Qujian(int x,int y,int i,int num){
    if(b[i].sum==num) return ;
    if(b[i].left ==x&&y== b[i].right){  b[i].sum=num;return ; }
    if(b[i].sum!=-1){
        b[2*i].sum=b[2*i+1].sum=b[i].sum;
        b[i].sum=-1;
    }
    int mid = (b[i].left+b[i].right)>>1;
    if(x>mid) Qujian(x,y,2*i+1,num);
    else if(y<=mid) Qujian(x,y,2*i,num);
    else { Qujian(mid+1,y,2*i+1,num); Qujian(x,mid,2*i,num); }

}
int sum_(int i){
    if(b[i].sum!=-1){  return (b[i].right-b[i].left+1)*b[i].sum; }
    else return  sum_(2*i+1)+sum_(2*i);
}
int main(){
    int t,kase=1;
    scanf("%d",&t);
    while(t--){

        memset(b,0,sizeof(b));
        int n,m;
        scanf("%d%d",&n,&m);
        build(1,n,1);
        while(m--){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            Qujian(x,y,1,z);

        }
        printf("Case %d: The total value of the hook is %d.\n",kase++,sum_(1));

    }
}

#include<bits/stdc++.h>
using namespace std;
#define N 100100

struct {
    int sum;
    int left,right;
    int lazy,tag;
}b[N*4];
void build(int left,int right,int i){
    int mid;
    b[i].left=left;b[i].right=right;b[i].sum=1;b[i].lazy=0;b[i].tag=0;
    if(left==right) {
        b[i].sum=1;
        return ;
    }
    mid = (left+right)/2;
    build(left,mid,2*i);
    build(mid+1,right,2*i+1);
}
void Updata(int x,int y,int i,int num){
    if(b[i].left ==x&&y== b[i].right){  b[i].sum=num*(b[i].right-b[i].left+1); b[i].lazy = 1; b[i].tag=num; return ; }
    int mid = (b[i].left+b[i].right)>>1;
    if(b[i].lazy==1){
        b[i].lazy=0;
        Updata(b[i].left,mid,i*2,b[i].tag);
        Updata(mid+1,b[i].right,i*2+1,b[i].tag);

    }

    if(x>mid) Updata(x,y,2*i+1,num);
    else if(y<=mid) Updata(x,y,2*i,num);
    else { Updata(mid+1,y,2*i+1,num); Updata(x,mid,2*i,num); }
    b[i].sum = b[i*2].sum + b[i*2+1].sum;
}
int main(){
    int t,kase=1;
    scanf("%d",&t);
    while(t--){

        memset(b,0,sizeof(b));
        int n,m;
        scanf("%d%d",&n,&m);
        build(1,n,1);
        while(m--){
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            Updata(x,y,1,z);

        }
        printf("Case %d: The total value of the hook is %d.\n",kase++,b[1].sum);

    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值