hdu 3397 Sequence operation 线段树 区间和 连续1的个数

这篇博客讲述了在解决HDU 3397问题中遇到的挑战,作者经历了多次提交错误并最终找到问题所在。该问题涉及到线段树的使用,主要包括区间内的数值置0、置1、旋转操作,以及查询区间和与计算连续1的个数。关键在于,当线段树节点的值不为-1时,不需要考虑异或操作,并在pushdown过程中将XOR设为0。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Sequence operation

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


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

  这题我交了几十次。。也不是说有多难。。有个地方写错了没发现。。隔几天看一看,今天终于发现了哪错了。。

  区间置0,置1,旋转,询问区间和 and 连续1的个数。

  只要set不是-1就不管XOR,pushdown的时候把XOR置0。

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<algorithm>
#define eps 1e-9
#define MAXN 100010
#define MAXM 55
#define MAXNODE MAXN*4
#define MOD 999983
typedef long long LL;
using namespace std;
int T,N,M;
int a[MAXN],sum[MAXNODE],setv[MAXNODE],l1[MAXNODE],l0[MAXNODE],r1[MAXNODE],r0[MAXNODE],m1[MAXNODE],m0[MAXNODE],XOR[MAXNODE];
void rotate(int o,int L,int R){
    sum[o]=R-L+1-sum[o];
    swap(l1[o],l0[o]);
    swap(r1[o],r0[o]);
    swap(m1[o],m0[o]);
    if(setv[o]!=-1) setv[o]^=1;
    XOR[o]^=1;
}
void maintain(int o,int L,int R){
    if(setv[o]!=-1){
        if(setv[o]==0){
            sum[o]=0;
            l1[o]=r1[o]=m1[o]=0;
            l0[o]=r0[o]=m0[o]=R-L+1;
        }
        if(setv[o]==1){
            sum[o]=R-L+1;
            l1[o]=r1[o]=m1[o]=R-L+1;
            l0[o]=r0[o]=m0[o]=0;
        }
        return;
    }
    int m=R-L+1;
    l0[o]=l0[o<<1];
    r0[o]=r0[o<<1|1];
    if(l0[o]==m-(m>>1)) l0[o]+=l0[o<<1|1];
    if(r0[o]==(m>>1))  r0[o]+=r0[o<<1];
    l1[o]=l1[o<<1];
    r1[o]=r1[o<<1|1];
    if(l1[o]==m-(m>>1)) l1[o]+=l1[o<<1|1];
    if(r1[o]==(m>>1))  r1[o]+=r1[o<<1];
    sum[o]=sum[o<<1]+sum[o<<1|1];
    m1[o]=max(m1[o<<1],m1[o<<1|1]);
    m1[o]=max(m1[o],r1[o<<1]+l1[o<<1|1]);
    m0[o]=max(m0[o<<1],m0[o<<1|1]);
    m0[o]=max(m0[o],r0[o<<1]+l0[o<<1|1]);
}
void build(int o,int L,int R){
    setv[o]=-1;
    XOR[o]=0;
    if(L==R){
        setv[o]=a[L];
        maintain(o,L,R);
        return;
    }
    int mid=(L+R)>>1;
    build(o<<1,L,mid);
    build(o<<1|1,mid+1,R);
    maintain(o,L,R);
}
void pushdown(int o,int L,int R){
    int mid=(L+R)>>1;
    if(setv[o]!=-1){
        setv[o<<1]=setv[o<<1|1]=setv[o];
        maintain(o<<1,L,mid);
        maintain(o<<1|1,mid+1,R);
        setv[o]=-1;
    }
    else if(XOR[o]){
        rotate(o<<1,L,mid);
        rotate(o<<1|1,mid+1,R);
    }
    XOR[o]=0;
}
void update(int o,int L,int R,int ql,int qr,int op){
    if(ql<=L&&qr>=R){
        if(op<2){
            setv[o]=op;
            maintain(o,L,R);
        }
        else rotate(o,L,R);
        return;
    }
    pushdown(o,L,R);
    int mid=(L+R)>>1;
    if(ql<=mid) update(o<<1,L,mid,ql,qr,op);
    if(qr>mid) update(o<<1|1,mid+1,R,ql,qr,op);
    maintain(o,L,R);
}
int query(int o,int L,int R,int ql,int qr,int op){
    if(ql<=L&&qr>=R){
        if(op==3) return sum[o];
        if(op==4) return m1[o];
    }
    pushdown(o,L,R);
    int ret=0,mid=(L+R)>>1;
    if(op==3){
        if(ql<=mid) ret+=query(o<<1,L,mid,ql,qr,op);
        if(qr>mid) ret+=query(o<<1|1,mid+1,R,ql,qr,op);
    }
    if(op==4){
        int n1=0,n2=0,n3=0;
        if(ql<=mid) n1=query(o<<1,L,mid,ql,qr,op);
        if(qr>mid) n2=query(o<<1|1,mid+1,R,ql,qr,op);
        if(ql<=mid&&qr>mid) n3=min(r1[o<<1],mid-ql+1)+min(l1[o<<1|1],qr-mid);
        ret=max(max(n1,n2),n3);
    }
    return ret;
}
int main(){
    freopen("in.txt","r",stdin);
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&N,&M);
        for(int i=1;i<=N;i++) scanf("%d",&a[i]);
        build(1,1,N);
        while(M--){
            int ql,qr,op;
            scanf("%d%d%d",&op,&ql,&qr);
            if(op<=2) update(1,1,N,ql+1,qr+1,op);
            else printf("%d\n",query(1,1,N,ql+1,qr+1,op));
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值