高度模式化的線段樹寫法

(水)

struct point{int l,r,val1,val2/*要維護的信息*/,tag1,tag2/*標記*/;}tree[maxn<<2];
point pushup(point x,point y,int tg1,int tg2/*標記傳進來*/)
{
    point ans;
    if(x.l==0)return y;//如果其中一個爲空直接返回另一個
    if(y.l==0)return x;
    ans.l=x.l;ans.r=y.r;
    ans.tag1=tg1;ans.tag2=tg2;
    /*這裏寫信息的pushup*/
    return ans;
}
void pushup(int x)
{
    int lson=x<<1,rson=lson|1;
    tree[x]=pushup(tree[lson],tree[rson],tree[x].tag1,tree[x].tag2);
}
void pushtag1(int x,int k)//有多個這樣的函數,每個函數處理一個 tag
{
    tree[x].tag=k;
    /*這裏寫對同結點其他標記的影響*/
    /*然後寫對同結點要維護的值的影響*/
}
void pushdown(int x)
{
    int lson=x<<1,rson=lson|1;
    if(tree[x].l==tree[x].r)return;
    if(tree[x].tag1!=0)
    {
        pushtag1(lson,tree[x].tag1);
        pushtag1(rson,tree[x].tag1);
        tree[x].tag1=0;
    }
}
void build(int x,int l,int r)
{
    tree[x]=(point){l,r,0,0,0};//清零
    if(l==r)
    {
        /*要維護的信息的初始化*/
        return;
    }
    int mid=(tree[x].l+tree[x].r)>>1,lson=x<<1,rson=lson|1;
    build(lson,l,mid);build(rson,mid+1,r);
    pushup(x);
}
void modify_tag1(int x,int l,int r,int k)
{
    pushdown(x);
    if(l<=tree[x].l&&r>=tree[x].r){pushtag1(x,k);return;}
    int mid=(tree[x].l+tree[x].r)>>1,lson=x<<1,rson=lson|1;
    if(l<=mid)modify_tag1(lson,l,r,k);
    if(r>mid)modify_tag1(rson,l,r,k);
    pushup(x);
}
point query_val1(int x,int l,int r)
{
    pushdown(x);
    if(l<=tree[x].l&&r>=tree[x].r)return tree[x];
    int mid=(tree[x].l+tree[x].r)>>1,lson=x<<1,rson=lson|1;
    point ans=(point){0,0,0,0,0};
    if(l<=mid)ans=pushup(query_val1(lson,l,r),ans,-1,0);
    if(r>mid)ans=pushup(ans,query_val1(rson,l,r),-1,0);
    return ans;
}

這種模板的好處是查詢的時候不用動腦子。
然後你就能做這道題了!

code:

const int maxn=100010;
int n,m,ans,cnt,a[maxn],p[maxn];
struct point{int l,r,sum,maxcon[2],lcon[2],rcon[2],cover,flip;}tree[maxn<<2];
//sum:區間內1的數量
//maxcon[2]:區間內最多連續0/1的數量
//lcon[2]:區間左端最多連續0/1的數量
//rcon[2]:區間右端最多連續0/1的數量
//cover:區間是否被覆蓋(-1:未被覆蓋,0/1:被覆蓋爲0/1)
//flip:區間是否被全部取反
point pushup(point x,point y,int cov,int flp)
{
    point ans;
    if(x.l==0)return y;
    if(y.l==0)return x;
    ans.l=x.l;ans.r=y.r;
    ans.cover=cov;ans.flip=flp;
    ans.sum=x.sum+y.sum;
    ans.maxcon[0]=max(max(x.maxcon[0],y.maxcon[0]),x.rcon[0]+y.lcon[0]);
    ans.maxcon[1]=max(max(x.maxcon[1],y.maxcon[1]),x.rcon[1]+y.lcon[1]);
    if(x.sum==0)ans.lcon[0]=x.r-x.l+1+y.lcon[0];
    else ans.lcon[0]=x.lcon[0];
    if(x.sum==x.r-x.l+1)ans.lcon[1]=x.r-x.l+1+y.lcon[1];
    else ans.lcon[1]=x.lcon[1];
    if(y.sum==0)ans.rcon[0]=y.r-y.l+1+x.rcon[0];
    else ans.rcon[0]=y.rcon[0];
    if(y.sum==y.r-y.l+1)ans.rcon[1]=y.r-y.l+1+x.rcon[1];
    else ans.rcon[1]=y.rcon[1];
    return ans;
}
void pushup(int x)
{
    int lson=x<<1,rson=lson|1;
    tree[x]=pushup(tree[lson],tree[rson],tree[x].cover,tree[x].flip);
}
void pushcover(int x,int k)
{
    tree[x].cover=k;
    tree[x].flip=0;
    if(k==0)
    {
        tree[x].sum=tree[x].maxcon[1]=tree[x].lcon[1]=tree[x].rcon[1]=0;
        tree[x].maxcon[0]=tree[x].lcon[0]=tree[x].rcon[0]=tree[x].r-tree[x].l+1;
    }
    else
    {
        tree[x].sum=tree[x].maxcon[1]=tree[x].lcon[1]=tree[x].rcon[1]=tree[x].r-tree[x].l+1;
        tree[x].maxcon[0]=tree[x].lcon[0]=tree[x].rcon[0]=0;
    }
}
void pushflip(int x)
{
    tree[x].flip^=1;
    tree[x].sum=tree[x].r-tree[x].l+1-tree[x].sum;
    swap(tree[x].maxcon[0],tree[x].maxcon[1]);
    swap(tree[x].lcon[0],tree[x].lcon[1]);
    swap(tree[x].rcon[0],tree[x].rcon[1]);
}
void pushdown(int x)
{
    int lson=x<<1,rson=lson|1;
    if(tree[x].l==tree[x].r)return;
    if(tree[x].cover!=-1)
    {
        pushcover(lson,tree[x].cover);
        pushcover(rson,tree[x].cover);
        tree[x].cover=-1;
    }
    if(tree[x].flip!=0)
    {
        pushflip(lson);
        pushflip(rson);
        tree[x].flip=0;
    }
}
void build(int x,int l,int r)
{
    tree[x]=(point){l,r,0,{0,0},{0,0},{0,0},-1,0};
    if(l==r)
    {
        if(a[l])tree[x].sum=tree[x].maxcon[1]=tree[x].lcon[1]=tree[x].rcon[1]=1;
        else tree[x].maxcon[0]=tree[x].lcon[0]=tree[x].rcon[0]=1;
        return;
    }
    int mid=(tree[x].l+tree[x].r)>>1,lson=x<<1,rson=lson|1;
    build(lson,l,mid);build(rson,mid+1,r);
    pushup(x);
}
void modify_cover(int x,int l,int r,int k)
{
    pushdown(x);
    if(l<=tree[x].l&&r>=tree[x].r){pushcover(x,k);return;}
    int mid=(tree[x].l+tree[x].r)>>1,lson=x<<1,rson=lson|1;
    if(l<=mid)modify_cover(lson,l,r,k);
    if(r>mid)modify_cover(rson,l,r,k);
    pushup(x);
}
void modify_flip(int x,int l,int r)
{
    pushdown(x);
    if(l<=tree[x].l&&r>=tree[x].r){pushflip(x);return;}
    int mid=(tree[x].l+tree[x].r)>>1,lson=x<<1,rson=lson|1;
    if(l<=mid)modify_flip(lson,l,r);
    if(r>mid)modify_flip(rson,l,r);
    pushup(x);
}
point query_sum(int x,int l,int r)
{
    pushdown(x);
    if(l<=tree[x].l&&r>=tree[x].r)return tree[x];
    int mid=(tree[x].l+tree[x].r)>>1,lson=x<<1,rson=lson|1;
    point ans=(point){0,0,0,{0,0},{0,0},{0,0},-1,0};
    if(l<=mid)ans=pushup(query_sum(lson,l,r),ans,-1,0);
    if(r>mid)ans=pushup(ans,query_sum(rson,l,r),-1,0);
    return ans;
}
point query_maxcon(int x,int l,int r)
{
    pushdown(x);
    if(l<=tree[x].l&&r>=tree[x].r)return tree[x];
    int mid=(tree[x].l+tree[x].r)>>1,lson=x<<1,rson=lson|1;
    point ans=(point){0,0,0,{0,0},{0,0},{0,0},-1,0};
    if(l<=mid)ans=pushup(query_maxcon(lson,l,r),ans,-1,0);
    if(r>mid)ans=pushup(ans,query_maxcon(rson,l,r),-1,0);
    return ans;
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)a[i]=read();
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        int opt=read(),ll=read()+1,rr=read()+1;
        switch(opt)
        {
            case 0:modify_cover(1,ll,rr,0);break;
            case 1:modify_cover(1,ll,rr,1);break;
            case 2:modify_flip(1,ll,rr);break;
            case 3:printf("%d\n",query_sum(1,ll,rr).sum);break;
            case 4:printf("%d\n",query_maxcon(1,ll,rr).maxcon[1]);break;
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章