線段樹板子2

  區間修改O(log2(n))
ll st[MAXN<<2],stmin[MAXN<<2],stvis[MAXN<<2],stmax[MAXN<<2];
ll a[MAXN];
void push_up(int rt)
{
    stmax[rt]=max(stmax[lson],stmax[rson]);
    stmin[rt]=min(stmin[lson],stmin[rson]);
    st[rt]=st[lson]+st[rson];//修改位置
}
void push_down(int rt,int sec)          //rt標記節點 sec區間
{
	if(stvis[lson]==-1)
        stvis[lson]=0;
    stvis[lson]+=stvis[rt];
    st[lson]+=stvis[rt]*(sec-(sec>>1));
    stmin[lson]+=stvis[rt];
    stmax[lson]+=stvis[rt];

    if(stvis[rson]==-1)
        stvis[rson]=0;
    stvis[rson]+=stvis[rt];
    st[rson]+=stvis[rt]*(sec>>1);
    stmin[rson]+=stvis[rt];
    stmax[rson]+=stvis[rt];
    stvis[rt]=0;
}
void build(int l,int r,int rt)
{
    stvis[rt]=0;
    if(l==r)
    {
        stmax[rt]=stmin[rt]=st[rt]=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,lson);
    build(mid+1,r,rson);
    push_up(rt);
}
void update(int L,int R,ll v,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        stvis[rt]+=v;
        st[rt]+=v*(r-l+1);
        stmin[rt]+=v;
        stmax[rt]+=v;
        return;
    }
    if(stvis[rt])
        push_down(rt,r-l+1);
    int mid=(l+r)>>1;
    if(L<=mid)
        update(L,R,v,l,mid,lson);
    if(mid<R)
        update(L,R,v,mid+1,r,rson);
    push_up(rt);
}
void mod_update(int L,int R,int mod,int l,int r,int rt)//區間mod
{
    if(stmax[rt]<mod)
        return;
    if(l==r)
    {
        st[rt]%=mod;
        stmax[rt]=st[rt];
        return;
    }
    int mid=(l+r)>>1;
    if(L<=mid)
        mod_update(L,R,mod,l,mid,lson);
    if(mid<R)
        mod_update(L,R,mod,mid+1,r,rson);
    push_up(rt);
}
ll query(int L,int R,int l,int r,int rt)
{
    if(L<=l&&r<=R)
        return st[rt];
    if(stvis[rt])
        push_down(rt,r-l+1);
    int mid=(l+r)>>1;
    ll sum=0;
    if(L<=mid)
        sum+=query(L,R,l,mid,lson);//修改位置
    if(mid<R)
        sum+=query(L,R,mid+1,r,rson);//修改位置
    return sum;
}
區間合併
ll stl_len[MAXN<<2],str_len[MAXN<<2],stall[MAXN<<2],stvis[MAXN<<2];
void push_up(int rt,int sec)
{
    stl_len[rt]=stl_len[lson];
    if(stl_len[rt]==sec-(sec>>1))//是否左兒子整個區間都是符合條件的
        stl_len[rt]+=stl_len[rson];
    str_len[rt]=str_len[rson];
    if(str_len[rt]==(sec>>1))//是否右兒子整個區間都是符合條件的
        str_len[rt]+=str_len[lson];
    stall[rt]=max(str_len[lson]+stl_len[rson],max(stall[lson],stall[rson]));//左兒子的右區間與右兒子的左區間之和,左兒子的最長區間,右兒子的最長區間
}
void push_down(int rt,int sec)
{
    stvis[lson]=stvis[rt];
    stl_len[lson]=(sec-(sec>>1))*stvis[rt];
    str_len[lson]=(sec-(sec>>1))*stvis[rt];
    stall[lson]=(sec-(sec>>1))*stvis[rt];

    stvis[rson]=stvis[rt];
    stl_len[rson]=(sec>>1)*stvis[rt];
    str_len[rson]=(sec>>1)*stvis[rt];
    stall[rson]=(sec>>1)*stvis[rt];
    stvis[rt]=-1;
}
void build(int l,int r,int rt)
{
    stvis[rt]=-1;
    if(l==r)
    {
        stl_len[rt]=1;
        str_len[rt]=1;
        stall[rt]=1;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,lson);
    build(mid+1,r,rson);
    push_up(rt,r-l+1);
}
void update(int L,int R,ll v,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        stvis[rt]=v;
        stl_len[rt]=(r-l+1)*v;
        str_len[rt]=(r-l+1)*v;
        stall[rt]=(r-l+1)*v;
        return;
    }
    if(stvis[rt]!=-1)
        push_down(rt,r-l+1);
    int mid=(r+l)>>1;
    if(L<=mid)
        update(L,R,v,l,mid,lson);
    if(mid<R)
        update(L,R,v,mid+1,r,rson);
    push_up(rt,r-l+1);
}
int query(int v,int l,int r,int rt)
{
    if(l==r)
        return l;
    if(stvis[rt]!=-1)
        push_down(rt,r-l+1);
    int mid=(r+l)>>1;
    if(stall[lson]>=v)
        return query(v,l,mid,lson);
    else if(str_len[lson]+stl_len[rson]>=v)
        return mid-str_len[lson]+1;
    else
        return query(v,mid+1,r,rson);
}
區間異或
int stsum[MAXN<<2],stl_len[MAXN<<2][2],str_len[MAXN<<2][2],stall[MAXN<<2][2];
int stvis[MAXN<<2],stvis1[MAXN<<2];
int a[MAXN];
void change(int rt,int sec,int p)
{
    if(p<2)
    {
        stall[rt][p]=stl_len[rt][p]=str_len[rt][p]=sec;
        stall[rt][!p]=stl_len[rt][!p]=str_len[rt][!p]=0;
        stsum[rt]=p>0?sec:0;
        stvis[rt]=p;
    }
    else
    {
        swap(stall[rt][0],stall[rt][1]);
        swap(stl_len[rt][0],stl_len[rt][1]);
        swap(str_len[rt][0],str_len[rt][1]);
        stsum[rt]=sec-stsum[rt];
        stvis1[rt]^=1;
        if(stvis[rt]!=-1)
            stvis[rt]^=1;
    }
}
void push_up(int rt,int sec)
{
    stsum[rt]=stsum[lson]+stsum[rson];
    for(int i=0;i<2;i++)
    {
        stl_len[rt][i]=stl_len[lson][i];
        if(stl_len[rt][i]==sec-(sec>>1))
            stl_len[rt][i]+=stl_len[rson][i];
        str_len[rt][i]=str_len[rson][i];
        if(str_len[rt][i]==(sec>>1))
            str_len[rt][i]+=str_len[lson][i];
        stall[rt][i]=max(stall[lson][i],stall[rson][i]);
        stall[rt][i]=max(stall[rt][i],str_len[lson][i]+stl_len[rson][i]);
//        cout<<"****"<<stl_len[rt][i]<<"         "<<str_len[rt][i]<<"     "<<stall[rt][i]<<endl<<endl;
    }
//    cout<<"*************"<<stsum[rt]<<endl<<endl;
}
void push_down(int rt,int sec)
{
    if(stvis1[rt])
    {
        change(lson,sec-(sec>>1),2);
        change(rson,sec>>1,2);
        stvis1[rt]=0;
    }
    if(stvis[rt]!=-1)
    {
        change(lson,sec-(sec>>1),stvis[rt]);
        change(rson,sec>>1,stvis[rt]);
        stvis[rt]=-1;
    }
}
void build(int l,int r,int rt)
{
    stvis[rt]=-1,stvis1[rt]=0;
    if(l==r)
    {
        stl_len[rt][a[l]]=str_len[rt][a[l]]=stall[rt][a[l]]=1;
        stl_len[rt][!a[l]]=str_len[rt][!a[l]]=stall[rt][!a[l]]=0;
        stsum[rt]=a[l]?1:0;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,lson);
    build(mid+1,r,rson);
    push_up(rt,r-l+1);
}
void update(int L,int R,int p,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        change(rt,r-l+1,p);
        return;
    }
    push_down(rt,r-l+1);
    int mid=(l+r)>>1;
    if(L<=mid)
        update(L,R,p,l,mid,lson);
    if(mid<R)
        update(L,R,p,mid+1,r,rson);
    push_up(rt,r-l+1);
}
int query(int L,int R,int p,int l,int r,int rt)
{
    if(L<=l&&r<=R)
    {
        if(p==3)
            return stsum[rt];
        else
            return stall[rt][1];
    }
    push_down(rt,r-l+1);
    int sum=0;
    int mid=(l+r)>>1;
    if(p==3)
    {
        if(L<=mid)
            sum+=query(L,R,p,l,mid,lson);
        if(mid<R)
            sum+=query(L,R,p,mid+1,r,rson);
    }
    else
    {
        if(L<=mid)
            sum=max(sum,query(L,R,p,l,mid,lson));
        if(mid<R)
            sum=max(sum,query(L,R,p,mid+1,r,rson));
        sum=max(sum,min(str_len[lson][1],mid-L+1)+min(stl_len[rson][1],R-mid));
    }
    return sum;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        build(1,n,1);
        while(m--)
        {
            int op,c,b;
            scanf("%d%d%d",&op,&c,&b);
            c++,b++;
            if(op<3)
                update(c,b,op,1,n,1);
            else
                printf("%d\n",query(c,b,op,1,n,1));
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章