线段树(二)区间更新

hdu 1698

调试了很久,没想到一次ac了。

注意:区间更新中用到一种技术,延迟更新pushdown(v)。如果不使用延迟更新,而一个个的更新,长度为n的区间更新需要nlogn,而数组直接更新只需要n。体现不出线段树的优势,容易超时。

需要注意的另一点,建树的时候所有节点的状态都要考虑好,由于我做这题时,没有考虑好内节点的状态,导致样例跑出23的结果。这发代码可以当做模板来用。
区间更新线段树通常会出现一个段内的值(颜色等)不同的情况,需要进行标记清楚。


付ac代码:

#include<iostream>
#include<fstream>
#include<set>
#include<stack>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;


typedef long long LL;
const int MAX=0xfffffff;
const int mx=110000;
struct node{
    int l,r,col;
}tree[mx*4];


void pushdown(int v)
{
    if(tree[v].col!=-1)
    {
        tree[v*2].col=tree[v*2+1].col=tree[v].col;
        tree[v].col=-1;
    }
}
void build(int v,int l,int r)
{
    tree[v].l=l,tree[v].r=r,tree[v].col=1;
    if(l==r)
    {
        return;
    }
    int mid=(l+r)/2;build(v*2,l,mid),build(v*2+1,mid+1,r);
}
void update(int v,int l,int r,int col)
{
    if(tree[v].col==col)  return;
    if(tree[v].l==l&&tree[v].r==r)
    {
        tree[v].col=col;
        return ;
    }
    pushdown(v);
    int mid=(tree[v].l+tree[v].r)/2;
    if(l>mid)  update(v*2+1,l,r,col);
    else if(r<=mid)  update(v*2,l,r,col);
    else
    {
        update(v*2,l,mid,col);
        update(v*2+1,mid+1,r,col);
    }
}
int ans;
void query(int v,int l,int r)
{
    if(tree[v].l==l&&tree[v].r==r&&tree[v].col!=-1)
    {
        ans+=(tree[v].col)*(tree[v].r-tree[v].l+1);
        return ;
    }
    pushdown(v);
    int mid=(tree[v].l+tree[v].r)/2;
    if(l>mid)  query(v*2+1,l,r);
    else if(r<=mid)  query(v*2,l,r);
    else
    {
        query(v*2,l,mid);
        query(v*2+1,mid+1,r);
    }
}


int main( )
{
    //freopen("in.txt","r",stdin);
    int t;
    scanf("%d",&t);
    for(int ca=1;ca<=t;ca++)
    {
        int n,q;
        scanf("%d%d",&n,&q);
        build(1,1,n);
        for(int i=1;i<=q;i++)
        {
            int x,y,z;
            scanf("%d %d %d",&x,&y,&z);
            update(1,x,y,z);
        }
        ans=0;
        query(1,1,n);
        printf("Case %d: The total value of the hook is %d.\n",ca,ans);
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值