线段树易错点(仅限本人)

Sequence operation

更新区间,区间染色,区间合并

Q:

对于一个01序列
区间修改为0/1
区间每个数修改为异或
查询区间最长1序列
查询区间1的个数

易错点_1
标记先后顺序,能否同时存在(此题中我的写法同时存在会有BUG)
如:downFlag, update
void update(int o, int l, int r){
    int mid=(l+r)>>1, llen=mid-l+1, rlen=r-(mid+1)+1;
    if(l!=r){
        For(t,0,1){
            T[o].a[t].s=max(T[o<<1].a[t].ssuff+T[o<<1|1].a[t].spre,
                max(T[o<<1].a[t].s, T[o<<1|1].a[t].s));
            //pre
            if(T[o<<1].a[t].s==llen) T[o].a[t].spre=llen+T[o<<1|1].a[t].spre;
            else T[o].a[t].spre=T[o<<1].a[t].spre;
            //suff
            if(T[o<<1|1].a[t].s==rlen) T[o].a[t].ssuff=rlen+T[o<<1].a[t].ssuff;
            else T[o].a[t].ssuff=T[o<<1|1].a[t].ssuff;

            T[o].s[t]=T[o<<1].s[t]+T[o<<1|1].s[t];
        }
    }
    int c=T[o].c;
    if(c>=0) T[o].a[c]=(Data){r-l+1,r-l+1,r-l+1}, T[o].a[c^1]=(Data){0,0,0}, T[o].s[c]=r-l+1, T[o].s[1-c]=0;
    if(T[o].xo) swap(T[o].a[0], T[o].a[1]), swap(T[o].s[0], T[o].s[1]);
}
void downFlag(int o, int l, int r){
    int mid=(l+r)>>1;
    if(T[o].c>=0){           //Attention
        addFlag(T[o].c,LSON); addFlag(T[o].c,RSON);
        update(LSON); update(RSON);
        T[o].c=-1;
    }
    if(T[o].xo){             //Attention
        addFlag(-1,LSON); addFlag(-1,RSON);
        update(LSON); update(RSON);
        T[o].xo=0;
    }
}
易错点_2
叶节点更新时要特别注意
如:update, addFlag
void addFlag(int x, int o, int l, int r){
    if(l==r){             //Attention
        if(x>=0){
            T[o].a[x]=(Data){1,1,1}; T[o].a[x^1]=(Data){0,0,0};
            T[o].s[x]=1; T[o].s[1-x]=0;
        } else {
            swap(T[o].a[0], T[o].a[1]); swap(T[o].s[0], T[o].s[1]);
        }
    } else {
        if(x>=0) T[o].c=x, T[o].xo=0;
        else T[o].xo^=1;
    }
}

易错点_3

小细节
如:query
int query(int L, int R, int o, int l, int r, int xo){
    int sum=0;
    if(T[o].c>=0){
        if(T[o].c ^ xo ^ T[o].xo) sum=min(r, R)-max(l, L)+1;
        //注意区间长度,不要误写成r-l+1
    } else if(L<=l && r<=R){
        sum=T[o].s[xo^1];
    } else {
        int mid=(l+r)>>1;
        if(L<=mid) sum+=query(L, R, LSON, xo^T[o].xo);//注意算上区间的标记
        if(R>mid) sum+=query(L, R, RSON, xo^T[o].xo);
    }
    return sum;
}
附冗长代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#define File(x) "test."#x
#define For(i,s,e) for(int i=(s); i<=(e); i++)
#define Rep(i,s,e) for(int i=(s); i>=(e); i--)
#define LSON o<<1, l, mid
#define RSON o<<1|1, mid+1, r
using namespace std;

const int N=1000000+1;
struct Data{
    int s,spre,ssuff;
};
struct Node{
    Data a[2]; int c,s[2];
    bool xo;
}T[N];

int Q,n,m,val[N];

void update(int o, int l, int r){
    int mid=(l+r)>>1, llen=mid-l+1, rlen=r-(mid+1)+1;
    if(l!=r){               //Attention
        For(t,0,1){
            T[o].a[t].s=max(T[o<<1].a[t].ssuff+T[o<<1|1].a[t].spre,
                max(T[o<<1].a[t].s, T[o<<1|1].a[t].s));
            //pre
            if(T[o<<1].a[t].s==llen) T[o].a[t].spre=llen+T[o<<1|1].a[t].spre;
            else T[o].a[t].spre=T[o<<1].a[t].spre;
            //suff
            if(T[o<<1|1].a[t].s==rlen) T[o].a[t].ssuff=rlen+T[o<<1].a[t].ssuff;
            else T[o].a[t].ssuff=T[o<<1|1].a[t].ssuff;

            T[o].s[t]=T[o<<1].s[t]+T[o<<1|1].s[t];
        }
    }
    int c=T[o].c;
    if(c>=0) T[o].a[c]=(Data){r-l+1,r-l+1,r-l+1}, T[o].a[c^1]=(Data){0,0,0}, T[o].s[c]=r-l+1, T[o].s[1-c]=0;
    if(T[o].xo) swap(T[o].a[0], T[o].a[1]), swap(T[o].s[0], T[o].s[1]);
}
void build(int o, int l, int r){
    T[o].xo=0; T[o].c=-1;
    if(l==r){
        T[o].a[val[l]]=(Data){1,1,1}; T[o].a[val[l]^1]=(Data){0,0,0};
        T[o].s[val[l]]=1; T[o].s[1-val[l]]=0;
        return;
    }
    int mid=(l+r)>>1;
    build(RSON); build(LSON);
    update(o,l,r);
}
void addFlag(int x, int o, int l, int r){
    if(l==r){                  //Attention
        if(x>=0){
            T[o].a[x]=(Data){1,1,1}; T[o].a[x^1]=(Data){0,0,0};
            T[o].s[x]=1; T[o].s[1-x]=0;
        } else {
            swap(T[o].a[0], T[o].a[1]); swap(T[o].s[0], T[o].s[1]);
        }
    } else {
        if(x>=0) T[o].c=x, T[o].xo=0;//Attention
        else T[o].xo^=1;
    }
}
void downFlag(int o, int l, int r){
    int mid=(l+r)>>1;
    if(T[o].c>=0){//Attention
        addFlag(T[o].c,LSON); addFlag(T[o].c,RSON);
        update(LSON); update(RSON);
        T[o].c=-1;
    }
    if(T[o].xo){
        addFlag(-1,LSON); addFlag(-1,RSON);
        update(LSON); update(RSON);
        T[o].xo=0;
    }
}
void modify(int x, int L, int R, int o, int l, int r){
    if(L<=l && r<=R){
        addFlag(x,o,l,r);
    } else {
        downFlag(o,l,r);
        int mid=(l+r)>>1;
        if(L<=mid) modify(x, L, R, LSON); else update(LSON);
        if(R>mid) modify(x, L, R, RSON);  else update(RSON);
    }
    update(o,l,r);
}
void query(int L, int R, int o, int l, int r, int xo, int &sum, int &spre, int &ssuff){
    if(T[o].c>=0){
        if(T[o].c ^ xo ^ T[o].xo) sum=min(r, R)-max(l, L)+1, spre=sum, ssuff=sum;
        //Attention
    } else if(L<=l && r<=R){
        sum=T[o].a[xo^1].s; spre=T[o].a[xo^1].spre; ssuff=T[o].a[xo^1].ssuff;
    } else {
        int _suml=0,_prel=0,_suffl=0,mid=(l+r)>>1,llen=mid-max(l, L)+1, rlen=min(R, r)-(mid+1)+1;
        int _sumr=0,_prer=0,_suffr=0;
        if(L<=mid) query(L,R,LSON,xo^T[o].xo,_suml,_prel,_suffl);
        if(R>mid) query(L,R,RSON,xo^T[o].xo,_sumr,_prer,_suffr);
        sum=max(_suffl+_prer, max(_suml, _sumr));
        //pre
        if(_suml==llen) spre=_suml+_prer;
        else spre=_prel;
        //suff
        if(_sumr==rlen) ssuff=_sumr+_suffl;
        else ssuff=_suffr;
    }
}
int query(int L, int R, int o, int l, int r, int xo){
    int sum=0;
    if(T[o].c>=0){
        if(T[o].c ^ xo ^ T[o].xo) sum=min(r, R)-max(l, L)+1;
    } else if(L<=l && r<=R){
        sum=T[o].s[xo^1];
    } else {
        int mid=(l+r)>>1;
        if(L<=mid) sum+=query(L, R, LSON, xo^T[o].xo);
        if(R>mid) sum+=query(L, R, RSON, xo^T[o].xo);
    }
    return sum;
}

int main()
{
    freopen(File(in),"r",stdin);
    freopen(File(out),"w",stdout);

//  ios::sync_with_stdio(false);

    scanf("%d",&Q);
    while(Q--){
        scanf("%d%d",&n,&m);
        For(i,1,n) scanf("%d",&val[i]);
        build(1,1,n);
        while(m--){
            int opt,a,b; scanf("%d%d%d",&opt,&a,&b);
            a++, b++;
            if(opt==0) modify(opt,a,b,1,1,n);
            if(opt==1) modify(opt,a,b,1,1,n);
            if(opt==2) modify(-1,a,b,1,1,n);
            if(opt==3) printf("%d\n",query(a,b,1,1,n,0));
            if(opt==4){
                int sum,pre,suff;
                query(a,b,1,1,n,0,sum,pre,suff);
                printf("%d\n",sum);
            }
        }
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值