线段树二 (持续更新)

HDU 1689

http://acm.hdu.edu.cn/showproblem.php?pid=1698

这道题是使用懒操作的入门级的题目,在线段树的结构体中,加一个flag标记该区间是否是同色的。当为同色,那么在更新或者查询的时候就可以偷懒了,有效降低时间复杂度。

//hdu 1698
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define MAX 100010
#define lson l,m,k<<1
#define rson m+1,r,k<<1|1
using namespace std;
typedef struct SEG
{
    int flag,v;
}Seg;
Seg seg[MAX<<2];
void Init(int l,int r,int k)
{
    seg[k].flag = 1;
    seg[k].v = 1;
    return ;
}
void PushDown(int k)
{
    if(seg[k].flag)
    {
        seg[k<<1].flag=seg[k<<1|1].flag=1;
        seg[k<<1].v=seg[k<<1|1].v=seg[k].v;
        seg[k].flag=0;
    }
}
void PushUp(int k)
{
    if(seg[k<<1].flag&&seg[k<<1|1].flag)
    {
        if(seg[k<<1].v==seg[k<<1|1].v)
        {
            seg[k].flag=1;
            seg[k].v=seg[k<<1].v;
        }
    }
}
void Update(int ll,int rr,int v,int l,int r,int k)
{
    if(ll==l&&rr==r)
    {
        seg[k].flag=1;
        seg[k].v=v;
        return;
    }
    int m = (l+r)>>1;
    PushDown(k);
    if(rr<=m)
        Update(ll,rr,v,lson);
    else if(ll>m)
        Update(ll,rr,v,rson);
    else
    {
        Update(ll,m,v,lson);
        Update(m+1,rr,v,rson);
    }
    PushUp(k);
}
int Query(int l,int r,int k)
{
    if(seg[k].flag)
    {
        return seg[k].v*(r-l+1);
    }
    int m = (l+r)>>1;
    return Query(lson)+Query(rson);
}
int main()
{
    int T;
    int n,q;
    int x,y,z;
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++)
    {
        scanf("%d%d",&n,&q);
        Init(1,n,1);
        while(q--)
        {
            scanf("%d%d%d",&x,&y,&z);
            Update(x,y,z,1,n,1);
        }
        printf("Case %d: The total value of the hook is %d.\n",cas,Query(1,n,1));
    }
    return 0;
}

HDU 3308 LCIS

http://acm.hdu.edu.cn/showproblem.php?pid=3308

这道题应该可以看成是一道区间合并的题目,在结构体中记录左端点起始的最大上升序列长度,右端点结束的最大长度,以及整个区间的最大长度。为了在PushUp的时候方便,我们在记一个左右端点的值。更新很简单,只要更新到叶子节点就行了。

只要在PushUp中注意一下就行了,具体见代码。

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#define lson l,m,k<<1
#define rson m+1,r,k<<1|1
#define MAX 100100
using namespace std;
typedef struct SEG
{
    int lv,rv;
    int lnum,mnum,rnum;
}Seg;
Seg seg[MAX<<2];

void PushUp(int l,int r,int k)
{
    int m = (l+r)>>1;
    seg[k].lv=seg[k<<1].lv;
    seg[k].rv=seg[k<<1|1].rv;
    if((m-l+1)==seg[k<<1].lnum&&seg[k<<1].rv<seg[k<<1|1].lv)
        seg[k].lnum=seg[k<<1].lnum+seg[k<<1|1].lnum;
    else
        seg[k].lnum=seg[k<<1].lnum;

    if((r-m)==seg[k<<1|1].rnum&&seg[k<<1].rv<seg[k<<1|1].lv)
        seg[k].rnum=seg[k<<1|1].rnum+seg[k<<1].rnum;
    else
        seg[k].rnum=seg[k<<1|1].rnum;

    if(seg[k<<1].rv<seg[k<<1|1].lv)
        seg[k].mnum=max(max(seg[k<<1].mnum,seg[k<<1|1].mnum),seg[k<<1].rnum+seg[k<<1|1].lnum);
    else
        seg[k].mnum=max(seg[k<<1].mnum,seg[k<<1|1].mnum);
    seg[k].mnum=max(seg[k].mnum,max(seg[k].lnum,seg[k].rnum));
}

void Init(int l,int r,int k)
{
    if(l==r)
    {
        scanf("%d",&seg[k].rv);
        seg[k].lv=seg[k].rv;
        seg[k].lnum=seg[k].mnum=seg[k].rnum=1;
        return ;
    }
    int m = (l+r)>>1;
    Init(lson);
    Init(rson);
    PushUp(l,r,k);
}

void Update(int id,int v,int l,int r,int k)
{
    if(l==r)
    {
        seg[k].lv=seg[k].rv=v;
        return ;
    }
    int m = (l+r)>>1;
    if(id<=m)
        Update(id,v,lson);
    else
        Update(id,v,rson);
    PushUp(l,r,k);
}
Seg Query(int ll,int rr,int l,int r,int k)
{
    if(ll==l&&rr==r)
    {
        return seg[k];
    }
    int m = (l+r)>>1;
    if(rr<=m)
        return Query(ll,rr,lson);
    else if(ll>m)
        return Query(ll,rr,rson);
    else
    {
        Seg a = Query(ll,m,lson);
        Seg b = Query(m+1,rr,rson);
        Seg ans ;
        ans.lv=a.lv,ans.rv=b.rv;
        if(a.lnum==(m-ll+1)&&a.rv<b.lv)
            ans.lnum=a.lnum+b.lnum;
        else
            ans.lnum=a.lnum;
        if(b.rnum==(rr-m)&&a.rv<b.lv)
            ans.rnum=b.rnum+a.rnum;
        else
            ans.rnum=b.rnum;
        if(a.rv<b.lv)
            ans.mnum=max(max(a.mnum,b.mnum),a.rnum+b.lnum);
        else
            ans.mnum=max(a.mnum,b.mnum);
        ans.mnum=max(max(ans.lnum,ans.rnum),ans.mnum);
        return ans;
    }
}

int main()
{
    int T,n,m;
    char op[4];
    int a,b;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        Init(1,n,1);
        while(m--)
        {
            scanf("%s%d%d",op,&a,&b);
            ++a;
            if(op[0]=='Q')
            {
                ++b;
                Seg ans = Query(a,b,1,n,1);
                printf("%d\n",ans.mnum);
            }
            else
                Update(a,b,1,n,1);
        }
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值