hdu3397 Sequence operation 线段树区间合并

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397

题意:一个0,1序列,有三种操作方式:1、把某子区间置为0;2、把某子区间置为1;3、把某子区间0,1置反;

有两种询问:1、某子区间中1的个数;2、某子区间连续的1的个数最长是多少

对于第一种询问,就是普通的区间查询,第二种是一个区间合并的过程,可能是左子区间,右子区间或者中间合并一下

对于三种操作,难点在于置反,需要用个lazy标记

我在状态中记录了某个区间中,0和1的个数,区间左边连续的0的个数,区间左边连续的1的个数,右边亦然,以及整个区间的连续的0最长的长度,和1最长的长度

之所以这么做,因为置反后,原来需要查1的,现在查0就好了

结构体的f表示这个区间是否有被置反,x则表示当前应该询问的是什么(x是1,表示这个已经是置反过了的区间,那么本来问1的现在得问0了),因为用的是数组,所以只需询问下标为x^1的即可

每次更新时,如果是前两种操作,那么直接对该区间进行覆盖,这是要将f,x置零,其他的就根据覆盖值是0还是1进行赋值,可以用异或运算,具体可见代码

代码写的很长很丑:

#include <cstdio>
#include <cstring>
const int MAX = 100010;
struct point
{
    int l[2],r[2],max[2],tag,x,sum[2];
    int f;
}p[MAX<<2];
int max(int a,int b)
{
    return (a>b)?a:b;
}
int min(int a,int b)
{
    return (a<b)?a:b;
}
void push_up(int l,int r,int rt)
{
    p[rt].l[p[rt].x] = p[rt<<1].l[p[rt<<1].x];
    p[rt].r[p[rt].x] = p[rt<<1|1].r[p[rt<<1|1].x];
    p[rt].l[p[rt].x^1] = p[rt<<1].l[p[rt<<1].x^1];
    p[rt].r[p[rt].x^1] = p[rt<<1|1].r[p[rt<<1|1].x^1];
    p[rt].sum[p[rt].x] = p[rt<<1].sum[p[rt<<1].x]+p[rt<<1|1].sum[p[rt<<1|1].x];
    p[rt].sum[p[rt].x^1] = p[rt<<1].sum[p[rt<<1].x^1]+p[rt<<1|1].sum[p[rt<<1|1].x^1];
    int mid = l+r>>1;
    if(p[rt].l[p[rt].x]==mid-l+1) p[rt].l[p[rt].x]+=p[rt<<1|1].l[p[rt<<1|1].x];
    if(p[rt].r[p[rt].x]==r-mid) p[rt].r[p[rt].x]+=p[rt<<1].r[p[rt<<1].x];
    if(p[rt].l[p[rt].x^1]==mid-l+1) p[rt].l[p[rt].x^1]+=p[rt<<1|1].l[p[rt<<1|1].x^1];
    if(p[rt].r[p[rt].x^1]==r-mid) p[rt].r[p[rt].x^1]+=p[rt<<1].r[p[rt<<1].x^1];
    p[rt].max[p[rt].x] = max(max(p[rt<<1].max[p[rt<<1].x],p[rt<<1|1].max[p[rt<<1|1].x]),p[rt<<1].r[p[rt<<1].x]+p[rt<<1|1].l[p[rt<<1|1].x]);
    p[rt].max[p[rt].x^1] = max(max(p[rt<<1].max[p[rt<<1].x^1],p[rt<<1|1].max[p[rt<<1|1].x^1]),p[rt<<1].r[p[rt<<1].x^1]+p[rt<<1|1].l[p[rt<<1|1].x^1]);
    p[rt].tag = (p[rt<<1].tag==p[rt<<1|1].tag)?p[rt<<1].tag:-1;
}
void push_down(int l,int r,int rt)
{
    int mid = r+l>>1;
    if(p[rt].tag!=-1)
    {
        p[rt<<1].tag = p[rt<<1|1].tag = p[rt].tag;
        p[rt<<1].l[p[rt].tag] = p[rt<<1].r[p[rt].tag] = p[rt<<1].max[p[rt].tag] = mid-l+1;
        p[rt<<1].l[p[rt].tag^1] = p[rt<<1].r[p[rt].tag^1] = p[rt<<1].max[p[rt].tag^1] = 0;
        p[rt<<1|1].l[p[rt].tag] = p[rt<<1|1].r[p[rt].tag] = p[rt<<1|1].max[p[rt].tag] = r-mid;
        p[rt<<1|1].l[p[rt].tag^1] = p[rt<<1|1].r[p[rt].tag^1] = p[rt<<1|1].max[p[rt].tag^1] = 0;
        p[rt<<1].x = p[rt<<1|1].x = 0;
        p[rt<<1].f = p[rt<<1|1].f = 0;
        p[rt<<1].sum[p[rt].tag] = mid-l+1;
        p[rt<<1].sum[p[rt].tag^1] = 0;
        p[rt<<1|1].sum[p[rt].tag] = r-mid;
        p[rt<<1|1].sum[p[rt].tag^1] = 0;
    }
    else if(p[rt].f)
    {
        if(p[rt<<1].tag!=-1)
        {
            p[rt<<1].tag^=1;
            p[rt<<1].f = 0;
            p[rt<<1].x^=1;
        }
        else
        {
            p[rt<<1].f ^= 1;
            p[rt<<1].x ^= 1;
        }
        if(p[rt<<1|1].tag!=-1)
        {
            p[rt<<1|1].tag^=1;
            p[rt<<1|1].f = 0;
            p[rt<<1|1].x ^= 1;
        }
        else
        {
            p[rt<<1|1].f ^= 1;
            p[rt<<1|1].x ^= 1;
        }
        p[rt].f = 0;
    }
}
void build(int l,int r,int rt)
{
    p[rt].x = p[rt].f = 0;
    if(l==r)
    {
        int x;
        scanf("%d",&x);
        p[rt].tag = x;
        p[rt].l[0] = p[rt].r[0] = p[rt].max[0] = x ^ 1;
        p[rt].l[1] = p[rt].r[1] = p[rt].max[1] = x;
        p[rt].x = 0;
        p[rt].f = 0;
        p[rt].sum[x] = 1;
        p[rt].sum[x^1] = 0;
        return;
    }
    int mid = l+r>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    push_up(l,r,rt);
}
void update(int flag,int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        if(flag<2)
        {
            p[rt].tag = flag;
            p[rt].sum[0] = p[rt].l[0] = p[rt].r[0] = p[rt].max[0] = (flag^1)*(r-l+1);
            p[rt].sum[1] = p[rt].l[1] = p[rt].r[1] = p[rt].max[1] = (flag)*(r-l+1);
            p[rt].x = 0;
            p[rt].f = 0;
        }
        else
        {
            p[rt].x ^= 1;
            p[rt].f ^= 1;
            if(p[rt].tag!=-1)
            {
                p[rt].tag^=1;
                p[rt].f = 0;
            }
        }
        return;
    }
    int mid = r+l>>1;
    push_down(l,r,rt);
    if(L<=mid) update(flag,L,R,l,mid,rt<<1);
    if(R>mid) update(flag,L,R,mid+1,r,rt<<1|1);
    push_up(l,r,rt);
}
int query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    return p[rt].max[p[rt].x^1];
    int mid = r+l>>1;
    push_down(l,r,rt);
    int ans = 0;
    if(R<=mid) ans =  query(L,R,l,mid,rt<<1);
    else if(L>mid) ans =  query(L,R,mid+1,r,rt<<1|1);
    else
    {
        int tmp = 0;
        int l0 = mid-p[rt<<1].r[p[rt<<1].x^1]+1;
        int l1 = mid+p[rt<<1|1].l[p[rt<<1|1].x^1];
        tmp = min(R,l1)-max(l0,L)+1;
        ans = max(max(query(L,R,l,mid,rt<<1),query(L,R,mid+1,r,rt<<1|1)),tmp);
    }
   // push_up(l,r,rt);
    return ans;
}
int query1(int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    return p[rt].sum[p[rt].x^1];
    int mid = r+l>>1;
    push_down(l,r,rt);
    int ans = 0;
    if(L<=mid) ans+=query1(L,R,l,mid,rt<<1);
    if(R>mid) ans+=query1(L,R,mid+1,r,rt<<1|1);
   // push_up(l,r,rt);
    return ans;
}
int main()
{
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        int n,m,c,x,y;
        scanf("%d%d",&n,&m);
        build(0,n-1,1);
        while(m--)
        {
            scanf("%d%d%d",&c,&x,&y);
            if(c<3)
            update(c,x,y,0,n-1,1);
            else if(c==3)
            printf("%d\n",query1(x,y,0,n-1,1));
            else printf("%d\n",query(x,y,0,n-1,1));
        }
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值