HDU 3397——Sequence operation(线段树,区间染色+区间异或+区间合并)

Sequence operation

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


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
 


———————————————————————分割线————————————————

题目大意:

给定一个n个数的序列,有5种操作

1: 0 a b 将区间[a,b]覆盖为0

2:1 a b 将区间[a,b]覆盖为1

3:2 a b 将区间[a,b] 0变成1,1变成0

4:3 a b 查询区间[a,b]1的个数

5:4 a b 查询区间[a,b]连续1的个数


思路:

push_up 维护:

                      左连续,右连续,总连续的0/1的个数

                      总的1的个数

push_down lazy标记:

                     覆盖标记,异或标记


当某节点的信息被修改时,要push_up,对于异或标记和覆盖标记 要优先考虑覆盖标记,再考虑异或标记

查找区间的时候要push_down



细节好重要!!!加深理解push_up,push_down


#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

const int maxn=100001;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
int lc[maxn<<2],rc[maxn<<2],mc[maxn<<2];
int lc0[maxn<<2],rc0[maxn<<2],mc0[maxn<<2];
int cov[maxn<<2],Xor[maxn<<2],sum[maxn<<2];

void f_xor(int rt,int m)
{
    if(cov[rt]!=-1) cov[rt]^=1;
    else Xor[rt]^=1;
    swap(lc[rt],lc0[rt]);
    swap(rc[rt],rc0[rt]);
    swap(mc[rt],mc0[rt]);
    sum[rt]=m-sum[rt];
}
void f_cov(int rt,int m,int c)
{
    cov[rt]=c;
    Xor[rt]=0;
    lc0[rt]=rc0[rt]=mc0[rt]=c ?0:m;
    lc[rt]=rc[rt]=mc[rt]=sum[rt]=c ? m:0;
}
void push_down(int rt,int m)
{
    if(cov[rt]!=-1) {
        f_cov(rt<<1,m-(m>>1),cov[rt]);
        f_cov(rt<<1|1,m>>1,cov[rt]);
        cov[rt]=-1;
        Xor[rt]=0;
    }
    if(Xor[rt]) {
        f_xor(rt<<1,m-(m>>1));
        f_xor(rt<<1|1,m>>1);
        Xor[rt]=0;
    }
}
void push_up(int rt,int m)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];

    lc[rt]=lc[rt<<1];
    rc[rt]=rc[rt<<1|1];
    if(lc[rt]==m-(m>>1))
        lc[rt]+=lc[rt<<1|1];
    if(rc[rt]==m>>1)
        rc[rt]+=rc[rt<<1];
    mc[rt]=max(rc[rt<<1]+lc[rt<<1|1],max(mc[rt<<1],mc[rt<<1|1]));

    lc0[rt]=lc0[rt<<1];
    rc0[rt]=rc0[rt<<1|1];
    if(lc0[rt]==m-(m>>1))
        lc0[rt]+=lc0[rt<<1|1];
    if(rc0[rt]==m>>1)
        rc0[rt]+=rc0[rt<<1];
    mc0[rt]=max(lc0[rt<<1|1]+rc0[rt<<1],max(mc0[rt<<1],mc0[rt<<1|1]));
}
void build(int l,int r,int rt)
{
    cov[rt]=-1;
    Xor[rt]=0;
    if(l==r) {
        scanf("%d",&sum[rt]);
        cov[rt]=lc[rt]=rc[rt]=mc[rt]=sum[rt];
        lc0[rt]=rc0[rt]=mc0[rt]= 1-sum[rt];
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    push_up(rt,r-l+1);
}
void update(int op,int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R) {
        if(op==0)
            f_cov(rt,r-l+1,0);
        if(op==1)
            f_cov(rt,r-l+1,1);
        if(op==2)
            f_xor(rt,r-l+1);
        return ;
    }
    push_down(rt,r-l+1);
    int m=(l+r)>>1;
    if(L<=m) update(op,L,R,lson);
    if(m<R) update(op,L,R,rson);
    push_up(rt,r-l+1);
}
int query_sum(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R) {
        return sum[rt];
    }
    push_down(rt,r-l+1);
    int m=(l+r)>>1;
    int ans=0;
    if(L<=m)
        ans+=query_sum(L,R,lson);
    if(m<R)
        ans+=query_sum(L,R,rson);
    return ans;
}
int query_len(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R) {
        return mc[rt];
    }
    push_down(rt,r-l+1);
    int m=(l+r)>>1;
    int ans=0;
    if(L<=m)
        ans=max(ans,query_len(L,R,lson));
    if(m<R)
        ans=max(ans,query_len(L,R,rson));
    return max(ans,min(m-L+1,rc[rt<<1])+min(R-m,lc[rt<<1|1]));
}
int main()
{
    int T,n,m;
    cin>>T;
    while(T--) {
        scanf("%d %d",&n,&m);
        build(0,n-1,1);
        int op,l,r;
        while(m--) {
            scanf("%d %d %d",&op,&l,&r);
            if(op<=2)
                update(op,l,r,0,n-1,1);
            if(op==3)
                printf("%d\n",query_sum(l,r,0,n-1,1));
            if(op==4)
                printf("%d\n",query_len(l,r,0,n-1,1));
        }
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值