HDU 3397 Sequence operation(线段树区间合并+区间修改)

Sequence operation

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 8568    Accepted Submission(s): 2593


Problem Description
lxhgww got a sequence contains n characters which are all '0's or '1's.
We have five operations here:
Change operations:
0 a b change all characters into '0's in [a , b]
1 a b change all characters into '1's in [a , b]
2 a b change all '0's into '1's and change all '1's into '0's in [a, b]
Output operations:
3 a b output the number of '1's in [a, b]
4 a b output the length of the longest continuous '1' string in [a , b]
 

Input
T(T<=10) in the first line is the case number.
Each case has two integers in the first line: n and m (1 <= n , m <= 100000).
The next line contains n characters, '0' or '1' separated by spaces.
Then m lines are the operations:
op a b: 0 <= op <= 4 , 0 <= a <= b < n.
 

Output
For each output operation , output the result.
 

Sample Input
 
 
1 10 10 0 0 0 1 1 0 1 0 1 1 1 0 2 3 0 5 2 2 2 4 0 4 0 3 6 2 3 7 4 2 8 1 0 5 0 5 6 3 3 9
 

Sample Output
 
 
5 2 6 5

这里Push_down要格外注意,add[rt]实际上表示的是需要更新的
子树,所以要防止add[lson]的值被覆盖的情况。

代码:

#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
#define lson rt<<1
#define rson rt<<1|1
const int maxn=1e5+7;
int a[maxn],add[maxn<<2];
struct node
{
    int left,right,mid;
    int lx0,rx0,mx0;
    int lx1,rx1,mx1;
    int dis()
    {
        return right-left+1;
    }
    int num;
} c[maxn<<2];
int pp(int op,int rt)
{
    if(add[rt]==-1)return op;
    if(op==1) return 1;
    if(op==0) return 0;
    if(op==2&&add[rt]==2) return -1;
    return add[rt]^1;
}
void change(int op,int rt)
{
    if(op==0)
    {
        c[rt].lx0=c[rt].rx0=c[rt].mx0=c[rt].dis();
        c[rt].lx1=c[rt].rx1=c[rt].mx1=0;
        c[rt].num=0;
    }
    else if(op==1)
    {
        c[rt].lx0=c[rt].rx0=c[rt].mx0=0;
        c[rt].lx1=c[rt].rx1=c[rt].mx1=c[rt].dis();
        c[rt].num=c[rt].dis();
    }
    else
    {
        swap(c[rt].lx0,c[rt].lx1);
        swap(c[rt].rx0,c[rt].rx1);
        swap(c[rt].mx0,c[rt].mx1);
        c[rt].num=c[rt].dis()-c[rt].num;
    }
}
void Push_down(int rt)
{
    if(c[rt].left==c[rt].right)
        return;
    int op=add[rt];
    if(op==-1)return;
    add[rt]=-1;
    add[lson]=pp(op,lson);
    add[rson]=pp(op,rson);
    change(op,lson);
    change(op,rson);
}
void Push_up(int rt)
{
    c[rt].lx0=c[lson].lx0;
    if(c[lson].lx0==c[lson].dis())
        c[rt].lx0+=c[rson].lx0;
    c[rt].rx0=c[rson].rx0;
    if(c[rson].rx0==c[rson].dis())
        c[rt].rx0+=c[lson].rx0;
    c[rt].mx0=max(max(c[lson].mx0,c[rson].mx0),c[lson].rx0+c[rson].lx0);
    c[rt].lx1=c[lson].lx1;
    if(c[lson].lx1==c[lson].dis())
        c[rt].lx1+=c[rson].lx1;
    c[rt].rx1=c[rson].rx1;
    if(c[rson].rx1==c[rson].dis())
        c[rt].rx1+=c[lson].rx1;
    c[rt].mx1=max(max(c[lson].mx1,c[rson].mx1),c[lson].rx1+c[rson].lx1);
    c[rt].num=c[lson].num+c[rson].num;
}
void build(int l,int r,int rt)
{
    c[rt].left=l;
    c[rt].right=r;
    c[rt].mid=(l+r)>>1;
    if(l==r)
    {
        c[rt].lx0=c[rt].rx0=c[rt].mx0=a[l]^1;
        c[rt].lx1=c[rt].rx1=c[rt].mx1=a[l];
        c[rt].num=a[l];
        return;
    }
    build(l,c[rt].mid,lson);
    build(c[rt].mid+1,r,rson);
    Push_up(rt);
}
void update(int op,int l,int r,int rt)
{
    Push_down(rt);
    if(l==c[rt].left&&r==c[rt].right)
    {
        add[rt]=op;
        //pp(op,add[rt]);
        //if(add[rt]!=-1)
            change(op,rt);
        return;
    }
    if(r<=c[rt].mid) update(op,l,r,lson);
    else if(l>c[rt].mid) update(op,l,r,rson);
    else
    {
        update(op,l,c[rt].mid,lson);
        update(op,c[rt].mid+1,r,rson);
    }
    Push_up(rt);
}
int query(int op,int l,int r,int rt)
{
    Push_down(rt);
    if(l==c[rt].left&&r==c[rt].right)
    {
        if(op==3)return c[rt].num;
        return c[rt].mx1;
    }
    if(r<=c[rt].mid)return query(op,l,r,lson);
    else if(l>c[rt].mid)return query(op,l,r,rson);
    else
    {
        int ll,rr,mm;
        ll=query(op,l,c[rt].mid,lson);
        rr=query(op,c[rt].mid+1,r,rson);
        if(op==3)return ll+rr;
        else
        {
            mm=min(c[rt].mid-l+1,c[lson].rx1)+min(r-c[rt].mid,c[rson].lx1);
            return max(max(ll,rr),mm);
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m,i,j;
        memset(add,-1,sizeof(add));
        scanf("%d%d",&n,&m);
        for(i=1; i<=n; i++)
            scanf("%d",&a[i]);
        build(1,n,1);
        while(m--)
        {
            int op,x,y;
            scanf("%d%d%d",&op,&x,&y);
            if(op<3) update(op,x+1,y+1,1);
            else printf("%d\n",query(op,x+1,y+1,1));
        }
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值