专题 线段树 E(区间更新,使用lazy标记)

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
const int MAXN=100010;
typedef long long LL;
int lazy[3*MAXN];                         //懒惰标记数组
int num[MAXN];
struct Node
{
    int l,r;
    LL nSum;
}segTree[MAXN*3];
void pushdown(int root,int len)                     //len为变动区间长度
{
    if(lazy[root]) {
                        lazy[root<<1]=lazy[root];                  //更新原值
                        lazy[(root<<1)+1]=lazy[root];
                        segTree[root<<1].nSum=(LL)(lazy[root]*(len-(len>>1)));           //更新sum值
                        segTree[(root<<1)+1].nSum=(LL)(lazy[root]*(len>>1));                    //以上两个式子不可改变
                        lazy[root]=0;
                        }
}
void Build(LL i,LL l,LL r)            //1 1 n
{
    segTree[i].l=l;
    segTree[i].r=r;
    if(l==r)
    {
        segTree[i].nSum=num[l];
        return;
    }
    LL mid=(l+r)>>1;                //右移运算符,除以2的n次
    Build(i<<1,l,mid);                    //左移运算符,乘以2的n次
    Build((i<<1)+1,mid+1,r);
    segTree[i].nSum=(LL)(segTree[i<<1].nSum+segTree[(i<<1)+1].nSum);            //父节点的值为两子节点之和
}
void pushup(int root)
{
    segTree[root].nSum=(LL)(segTree[root<<1].nSum+segTree[(root<<1)+1].nSum);
}
//未完成由下向上的更新
void Add(int i,int t,LL b,int val)                        //由上至下到达查找点,由下向上的更新,t b为区间,val为变动值
{
    /*segTree[i].nSum+=b;
    if(segTree[i].l==t&&segTree[i].r==t)   return;            //不更新叶节点
    LL mid=(segTree[i].l+segTree[i].r)>>1;
    if(t<=mid)  Add(i<<1,t,b);                            //判断左右节点
    else       Add((i<<1)+1,t,b);*/
    if(t==segTree[i].l&&b==segTree[i].r) {              //到达区间根节点
                                                              lazy[i]=val;
                                                              segTree[i].nSum=(LL) ((b-t+1)*val);
                                                              return;
                                                              }
    if(segTree[i].l==segTree[i].r) return;              //到达叶节点,未进行更新
    int mid=(segTree[i].l+segTree[i].r)>>1;
    pushdown(i,segTree[i].r-segTree[i].l+1);            //向下更新lazy标记
    if(t>mid) Add((i<<1)+1,t,b,val);                        //搜寻右子树
    else if(b<=mid) Add(i<<1,t,b,val);                      //搜寻左子树
            else {                                                              //区间在mid两边
                     Add(i<<1,t,mid,val);
                     Add((i<<1)+1,mid+1,b,val);
                    }
    pushup(i);
}
//查询
/*LL Query(LL i,LL l,LL r)
{
    if(l==segTree[i].l&&r==segTree[i].r)            //左右区间正好符合
       return segTree[i].nSum;
    pushdown(i, segTree[i].r - segTree[i].l + 1);                       //如果查询区间小于标记区间,则需要继续向下标记
    LL mid=(segTree[i].l+segTree[i].r)>>1;            //寻找中值
    if(r<=mid)  return Query(i<<1,l,r);                //区间在中值左侧
       else if(l>mid)   return Query((i<<1)+1,l,r);        //区间在中值右侧
            else  return Query(i<<1,l,mid)+Query((i<<1)+1,mid+1,r);        //区间在中值两侧分布
}*/
int main()
{
    int t,kase=0;
    scanf("%d",&t);
    while(t--)
    {
        memset(lazy,0,sizeof(lazy));
        int n,q;        //n为个数,q为操作数
        scanf("%d",&n);
        scanf("%d",&q);
        for(int i=1;i<=n;i++)
             num[i]=1;
        //memset(num,0,sizeof(num));
        Build(1,1,n);
        while(q--)
        {
            int x,y,z;                          //x y为操作区间,z为改变类型
            scanf("%d%d%d",&x,&y,&z);
            Add(1,x,y,z);
        }
        LL sum=segTree[1].nSum;
        printf("Case %d: The total value of the hook is ",++kase);
        cout<<sum<<"."<<endl;
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值