hdu 3397 Sequence operation(线段树,lazy,区间合并)


hdu 3397 Sequence operation


线段树lazy和区间合并结合的一个题,相当于几个题集中到一起嘛,分开想就好了

0,1,2操作都要lazy,2的异或操作找到每一只含1或只含0的区间进行取反

3的查询没啥好说的,最基础的求和查询

4的查询要用到区间合并的操作,需要注意的是查询区间跨左右儿子时要考虑跨区间的连续为1的段要在查询区间内


#include<cstdio>
#include<cstring>
#define MAXN 100005
#define lch p<<1
#define rch p<<1|1
//#define mid (t[p].l+t[p].r)>>1
struct node
{
    int l,r;
    int cover;
    int sum;
    int mx,lmx,rmx;
    //int getlen() {return r-l+1;}
    int len;
}t[MAXN<<2];
int max(int a,int b) {return a>b?a:b;}
int min(int a,int b) {return a<b?a:b;}
void pushup(int p)
{
    t[p].sum=t[lch].sum+t[rch].sum;
    
    t[p].mx=max(t[lch].mx,t[rch].mx);
    t[p].mx=max(t[p].mx,t[lch].rmx+t[rch].lmx);
    
    t[p].lmx=t[lch].lmx;
    if(t[lch].lmx==t[lch].len) t[p].lmx+=t[rch].lmx;
    
    t[p].rmx=t[rch].rmx;
    if(t[rch].rmx==t[rch].len) t[p].rmx+=t[lch].rmx;
}
void construct(int l,int r,int p)
{
    t[p].len=r-l+1;
    t[p].l=l,t[p].r=r;
    t[p].cover=-1;
    if(l==r)
    {
        scanf("%d",&t[p].mx);
        t[p].cover=t[p].lmx=t[p].rmx=t[p].sum=t[p].mx;
        return ;
    }
    int m=(t[p].l+t[p].r)>>1;
    construct(l,m,lch);
    construct(m+1,r,rch);
    pushup(p);
}
void refresh(int p)
{
    if(t[p].cover==0)
        t[p].mx=t[p].lmx=t[p].rmx=t[p].sum=0;
    else
        t[p].mx=t[p].lmx=t[p].rmx=t[p].sum=t[p].len;
}
void pushdown(int p)
{
    t[lch].cover=t[p].cover;
    t[rch].cover=t[p].cover;
    refresh(lch);
    refresh(rch);
    t[p].cover=-1;
}
void modify(int l,int r,int p,int op)
{
    if(t[p].l==l&&t[p].r==r)
    {
        t[p].cover=op;
        refresh(p);
        return ;
    }
    if(t[p].cover!=-1) pushdown(p);
    int m=(t[p].l+t[p].r)>>1;
    if(r<=m) modify(l,r,lch,op);
    else if(l>m) modify(l,r,rch,op);
    else modify(l,m,lch,op),modify(m+1,r,rch,op);
    pushup(p);
}
void modify_xor(int l,int r,int p)
{
    if(t[p].l==l&&t[p].r==r&&(t[p].sum==0||t[p].sum==t[p].len))
    {
        if(t[p].sum) t[p].cover=0;
        else t[p].cover=1;
        refresh(p);
        return ;
    }
    if(t[p].cover!=-1) pushdown(p);
    int m=(t[p].l+t[p].r)>>1;
    if(r<=m) modify_xor(l,r,lch);
    else if(l>m) modify_xor(l,r,rch);
    else modify_xor(l,m,lch),modify_xor(m+1,r,rch);
    pushup(p);
}
int query(int l,int r,int p)
{
    if(t[p].l==l&&t[p].r==r)
        return t[p].sum;
    if(t[p].cover!=-1) pushdown(p);
    int m=(t[p].l+t[p].r)>>1;
    if(r<=m) return query(l,r,lch);
    else if(l>m) return query(l,r,rch);
    else return query(l,m,lch)+query(m+1,r,rch);
}
int query_len(int l,int r,int p)
{
    if(t[p].l==l&&t[p].r==r)
        return t[p].mx;
    if(t[p].cover!=-1) pushdown(p);
    int m=(t[p].l+t[p].r)>>1;
    if(r<=m) return query_len(l,r,lch);
    else if(l>m) return query_len(l,r,rch);
    else
    {
        int ans=max(query_len(l,m,lch),query_len(m+1,r,rch));
        int lans=min(t[lch].rmx,t[lch].r-l+1),
        rans=min(t[rch].lmx,r-t[rch].l+1);
        return  ans=max(ans,lans+rans);
    }
}
int main()
{
    int cas,n,m,op,l,r;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d%d",&n,&m);
        construct(0,n-1,1);
        while(m--)
        {
            scanf("%d%d%d",&op,&l,&r);
            if(op==0)
                modify(l,r,1,0);
            else if(op==1)
                modify(l,r,1,1);
            else if(op==2)
                modify_xor(l,r,1);
            else if(op==3)
                printf("%d\n",query(l,r,1));
            else
                printf("%d\n",query_len(l,r,1));
        }
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值