M - Sequence operation HDU - 3397 线段树,成段更新,区间合并)

https://vjudge.net/contest/177550#problem/M

题意:

0 a b:将区间[a,b]全部置为0;

1 a b:将区间[a,b]全部置为1;

2 a b:对区间[a,b]进行异或操作;

3 a b:询问区间[a,b]内有多少个1;

4 a b:询问区间[a,b]内最长连续的1有多长。

参考别人的代码https://vjudge.net/solution/4424840,模仿下。。


#include<bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

#define sf scanf
#define pf printf
#define mem(a,b) memset(a,b,sizeof(a));
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define MP make_pair
#define LL   long long
#define inf 0x3f3f3f3f
#define ls (i<<1)
#define rs (ls|1)
#define md ((ll+rr)>>1)
#define lson ll,md,ls
#define rson md+1,rr,rs
#define eps 1e-5
#define N 100050
#define ree freopen("in.txt","r",stdin);
#define bug pf("----------------");

int mxL[2][N<<2],mxR[2][N<<2],mx[2][N<<2];
int sum[2][N<<2],cov[N<<2],Xor[N<<2];
void  init(int x,int i,int len){
    mxL[x][i]=mxR[x][i]=mx[x][i]=len;
    sum[x][i]=len;
}
void up(int x,int i,int ll,int rr){
    mxL[x][i]=mxL[x][ls],mxR[x][i]=mxR[x][rs];
    mx[x][i]=max(mx[x][ls],mx[x][rs]);
    mx[x][i]=max(mx[x][i],mxR[x][ls]+mxL[x][rs]);
    if(mxL[x][ls]==md-ll+1)
        mxL[x][i]+=mxL[x][rs];
    if(mxR[x][rs]==rr-md)
        mxR[x][i]+=mxR[x][ls];
    sum[x][i]=sum[x][ls]+sum[x][rs];
}
void build(int ll,int rr,int i){
    cov[i]=-1,Xor[i]=0;
    if(ll==rr){
        int v;
        sf("%d",&v);
        init(v,i,1);
        init(v^1,i,0);
        return;
    }
    build(lson),build(rson);
    up(0,i,ll,rr);
    up(1,i,ll,rr);
}
void change(int i){
    Xor[i]^=1;
    swap(mxL[0][i],mxL[1][i]);
    swap(mxR[0][i],mxR[1][i]);
    swap(mx[0][i],mx[1][i]);
    swap(sum[0][i],sum[1][i]);
}
void down(int i,int ll,int rr){
    if(cov[i]!=-1){
        int x=cov[i];
        cov[ls]=cov[rs]=x;
        Xor[ls]=Xor[rs]=0;
        init(x,ls,md-ll+1);
        init(x,rs,rr-md);
        init(x^1,ls,0);
        init(x^1,rs,0);
        cov[i]=-1;
    }
    if(Xor[i]){
        change(ls),change(rs);
        Xor[i]=0;
    }
}
void update(int l,int r,int op,int ll,int rr,int i){
    if(l==ll&&r==rr){
        if(op==0||op==1){
            init(op,i,rr-ll+1);
            init(op^1,i,0);
            cov[i]=op,Xor[i]=0;
        }
        else{
            change(i);
        }
        return;
    }
    down(i,ll,rr);
    if(r<=md)update(l,r,op,lson);
    else if(l>md)update(l,r,op,rson);
    else
        update(l,md,op,lson),update(md+1,r,op,rson);
    up(0,i,ll,rr);
    up(1,i,ll,rr);
}
int query(int l,int r,int op,int ll,int rr,int i){
    if(l==ll&&r==rr){
        if(op==4)
            return mx[1][i];
        else return sum[1][i];
    }
    down(i,ll,rr);
    int ret;
    if(r<=md)ret=query(l,r,op,lson);
    else if(l>md)ret=query(l,r,op,rson);
    else{
        int ret1=query(l,md,op,lson);
        int ret2=query(md+1,r,op,rson);
        if(op==4){
            ret=max(ret1,ret2);
            ret=max(ret,min(mxR[1][ls],md-l+1)+min(mxL[1][rs],r-md));
        }
        else ret=ret1+ret2;
    }
    up(0,i,ll,rr);
    up(1,i,ll,rr);
    return ret;
}
int main(){
    //ree
    int cas;
    sf("%d",&cas);
    while(cas--){
        int n,m;
        sf("%d%d",&n,&m);
        build(1,n,1);
        while(m--){
            int op,L,R;
            sf("%d%d%d",&op,&L,&R);
            ++L,++R;
            if(op<=2)
                update(L,R,op,1,n,1);
            else pf("%d\n",query(L,R,op,1,n,1));
        }
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值