hdu1698 Just a Hook (线段树)

题意:给一个大小为n的数组,初始状态全为1 ,进行q次段赋值,问最后的全段和是多少

思路:线段树段修改模板题(用来写模板的题)特别的是,由于只有最后一步查询全段和以及初始状态全为1,代码可以偷工减料

 #include <cstdio>
#include<iostream>
    using namespace std;
    const int maxn=500100;

    //用于存放线段树的结构 l,r表示此区间的左右端点
    struct segn
    {
        int su,mark_add;
    }segt[maxn];
    //建树:叶节点终止条件->递归建左右子树->由左右孩子信息得到此节点信息
    void push_dowm(int root,int st,int en)
    {
        if(segt[root].mark_add!=0)
        {
            segt[root*2+1].su=((st+en)/2-st+1)*segt[root].mark_add;
            segt[root*2+2].su=(en-(st+en)/2)*segt[root].mark_add;
            segt[root*2+1].mark_add=segt[root].mark_add;
            segt[root*2+2].mark_add=segt[root].mark_add;
            segt[root].mark_add=0;
        }
    }
    void build(int root,int st,int en)
    {
        //st,en表示目前区间的首尾端点序号,dat[]表示用于初始化的数据
        //记录左右端点

        if(st==en)//在叶子节点上加入元素数据
        {
            segt[root].mark_add=0;
            segt[root].su=1;//求区间和的操作
            return;
        }
        //对于非叶子节点
        int mid=(st+en)/2;//分割点
        //由二叉性,数组存树的左右节点编号分别为此节点的*2+1和*2+2
        build(root*2+1,st,mid);//递归建左子树
        build(root*2+2,mid+1,en);//右子树
        //由左右子树得到此节点的数据
        //求区间最小值

        //求区间和
        segt[root].su=segt[root*2+1].su+segt[root*2+2].su;
    }


    void segadd(int qst,int qen,int tst,int ten,int root,int addnum)
    {//全段加

        if(qst>ten||qen<tst)//不符合的区间
            {
                return ;
            }
        if(tst>=qst&&ten<=qen)//找到要加的区间
            {
                segt[root].mark_add=addnum;
                segt[root].su=addnum*(ten-tst+1);

                return ;
            }
        int mid =(tst+ten)/2;
push_dowm(root,tst,ten);
        segadd(qst,qen,tst,mid,root*2+1,addnum);
        segadd(qst,qen,mid+1,ten,root*2+2,addnum);//搜索左右子树
    }
    void upd(int root,int st,int en)
    {
        if(st==en)return;
        push_dowm(root,st,en);
        upd(2*root+1,st,(st+en)/2);
        upd(2*root+2,(st+en)/2+1,en);
        segt[root].su=segt[root*2+1].su+segt[root*2+2].su;
    }
    int main()
    {
       int c;
       scanf("%d",&c);
       for(int cas=1;cas<=c;cas++)
       {
           int n,q,st,en,va;
           scanf("%d%d",&n,&q);
           build(0,0,n-1);
           while(q--)
           {
               scanf("%d%d%d",&st,&en,&va);
               segadd(st-1,en-1,0,n-1,0,va);

           }upd(0,0,n-1);

          printf("Case %d: The total value of the hook is %d.\n",cas,segt[0].su);
       }
       return 0;
    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值