HDU 3397 Sequence operation(线段树区间更行)

题意:

给你一个01的串,有五种操作,第一种,将某个区间覆盖成0,第二种,将某个区间覆盖成1,第三种,将某个区间取反(即0变1,1变0),第四种,问某个区间1的个数,第五种,问某个区间最长连续的1的长度

思路:

超级超级超级麻烦的区间更新
首先,对于1,2,4操作,都是基础线段树的操作,5是基础区间更新的操作,但是此时多了一个3操作,导致写起来直接麻烦了很多
首先因为有异或和区间覆盖,我们可以维护lazy和Xor来节省时间,而因为我们需要取反,并且要迅速统计区间连续1最长的长度,我们就需要同时维护1和0的情况,因为只有在都维护的时候,我们才能快速处理取反操作(取反的时候我们只要交换0和1的数据即可)
说的很简单,但是代码量惊人,写起来贼麻烦,要处理好覆盖和异或的优先级,并且在处理lazy的时候,更新lsum,rsum,msum要处处注意细节

错误及反思:

虽然只wa了一次,但是找bug找了好久,强烈推荐dicuss里面老哥的数据,真的很管用

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int N = 100010;
int n,T,k,op,ta,tb,t;
int segtree[N<<2][2],lsum[N<<2][2],rsum[N<<2][2],msum[N<<2][2],lazy[N<<2],Xor[N<<2];
void pushdown(int l,int r,int rt)
{
    if(lazy[rt]!=-1)
    {
        int m=(l+r)/2;
        t=lazy[rt];
        lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
        Xor[rt<<1]=Xor[rt<<1|1]=0;

        segtree[rt<<1][t]=lsum[rt<<1][t]=rsum[rt<<1][t]=msum[rt<<1][t]=m-l+1;
        segtree[rt<<1][t^1]=lsum[rt<<1][t^1]=rsum[rt<<1][t^1]=msum[rt<<1][t^1]=0;

        segtree[rt<<1|1][t]=lsum[rt<<1|1][t]=rsum[rt<<1|1][t]=msum[rt<<1|1][t]=r-m;
        segtree[rt<<1|1][t^1]=lsum[rt<<1|1][t^1]=rsum[rt<<1|1][t^1]=msum[rt<<1|1][t^1]=0;
        lazy[rt]=-1;
    }
    else if(Xor[rt])
    {
        if(lazy[rt<<1]!=-1)
        {
            lazy[rt<<1]++;
            lazy[rt<<1]%=2;
        }
        else{
            Xor[rt<<1]++;
            Xor[rt<<1]%=2;
        }
        if(lazy[rt<<1|1]!=-1)
        {
            lazy[rt<<1|1]++;
            lazy[rt<<1|1]%=2;
        }
        else{
            Xor[rt<<1|1]++;
            Xor[rt<<1|1]%=2;
        }
        Xor[rt]=0;
        swap(segtree[rt<<1][0],segtree[rt<<1][1]);
        swap(lsum[rt<<1][0],lsum[rt<<1][1]);
        swap(rsum[rt<<1][0],rsum[rt<<1][1]);
        swap(msum[rt<<1][0],msum[rt<<1][1]);

        swap(segtree[rt<<1|1][0],segtree[rt<<1|1][1]);
        swap(lsum[rt<<1|1][0],lsum[rt<<1|1][1]);
        swap(rsum[rt<<1|1][0],rsum[rt<<1|1][1]);
        swap(msum[rt<<1|1][0],msum[rt<<1|1][1]);
    }
}
void pushup(int l,int r,int rt)
{
    int m=(l+r)/2;
    segtree[rt][0]=segtree[rt<<1][0]+segtree[rt<<1|1][0];
    segtree[rt][1]=segtree[rt<<1][1]+segtree[rt<<1|1][1];

    if(lsum[rt<<1][0]==m-l+1)
        lsum[rt][0]=lsum[rt<<1][0]+lsum[rt<<1|1][0];
    else lsum[rt][0]=lsum[rt<<1][0];

    if(rsum[rt<<1|1][0]==r-m)
        rsum[rt][0]=rsum[rt<<1][0]+rsum[rt<<1|1][0];
    else rsum[rt][0]=rsum[rt<<1|1][0];

    msum[rt][0]=max(rsum[rt<<1][0]+lsum[rt<<1|1][0],max(msum[rt<<1][0],msum[rt<<1|1][0]));

    if(lsum[rt<<1][1]==m-l+1)
        lsum[rt][1]=lsum[rt<<1][1]+lsum[rt<<1|1][1];
    else lsum[rt][1]=lsum[rt<<1][1];

    if(rsum[rt<<1|1][1]==r-m)
        rsum[rt][1]=rsum[rt<<1][1]+rsum[rt<<1|1][1];
    else rsum[rt][1]=rsum[rt<<1|1][1];

    msum[rt][1]=max(rsum[rt<<1][1]+lsum[rt<<1|1][1],max(msum[rt<<1][1],msum[rt<<1|1][1]));
}
void build(int l,int r,int rt)
{
    if(l==r)
    {
        scanf("%d",&t);
        segtree[rt][t]=lsum[rt][t]=rsum[rt][t]=msum[rt][t]=1;
        segtree[rt][t^1]=lsum[rt][t^1]=rsum[rt][t^1]=msum[rt][t^1]=0;
        return ;
    }
    int m=(l+r)/2;
    build(lson);
    build(rson);
    pushup(l,r,rt);
}
void change1(int L,int R,int v,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        lazy[rt]=v;
        Xor[rt]=0;
        segtree[rt][v]=lsum[rt][v]=rsum[rt][v]=msum[rt][v]=r-l+1;
        segtree[rt][v^1]=lsum[rt][v^1]=rsum[rt][v^1]=msum[rt][v^1]=0;
        return ;
    }
    pushdown(l,r,rt);
    int m=(l+r)/2;
    if(L<=m) change1(L,R,v,lson);
    if(R>m) change1(L,R,v,rson);
    pushup(l,r,rt);
}
void change2(int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        if(lazy[rt]!=-1)
        {
            lazy[rt]++;
            lazy[rt]%=2;
        }
        else{
            Xor[rt]++;
            Xor[rt]%=2;
        }
        swap(segtree[rt][0],segtree[rt][1]);
        swap(lsum[rt][0],lsum[rt][1]);
        swap(rsum[rt][0],rsum[rt][1]);
        swap(msum[rt][0],msum[rt][1]);
        return ;
    }
    pushdown(l,r,rt);
    int m=(l+r)/2;
    if(L<=m) change2(L,R,lson);
    if(R>m) change2(L,R,rson);
    pushup(l,r,rt);
}
int query1(int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
        return segtree[rt][1];
    pushdown(l,r,rt);
    int m=(l+r)/2;
    int ans=0;
    if(L<=m) ans+=query1(L,R,lson);
    if(R>m) ans+=query1(L,R,rson);
    pushup(l,r,rt);
    return ans;
}
int query2(int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
        return msum[rt][1];
    pushdown(l,r,rt);
    int m=(l+r)/2;
    if(R<=m) return query2(L,R,lson);
    if(L>m) return query2(L,R,rson);
    int ans=max(query2(L,R,lson),query2(L,R,rson));
    ans=max(ans,min(m-L+1,rsum[rt<<1][1])+min(R-m,lsum[rt<<1|1][1]));
    pushup(l,r,rt);
    return ans;
}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        memset(lazy,-1,sizeof(lazy));
        memset(Xor,0,sizeof(Xor));
        scanf("%d%d",&n,&k);
        build(0,n-1,1);
        while(k--)
        {
            scanf("%d%d%d",&op,&ta,&tb);
            if(op==0) change1(ta,tb,0,0,n-1,1);
            else if(op==1) change1(ta,tb,1,0,n-1,1);
            else if(op==2) change2(ta,tb,0,n-1,1);
            else if(op==3) printf("%d\n",query1(ta,tb,0,n-1,1));
            else printf("%d\n",query2(ta,tb,0,n-1,1));
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值