hdu3397(線段樹區間合併)

是一道坑題。。。大致的思維很好想,只要你知道區間合併,這題的結點維護的變量略多,這題需要用到lazy標記。我用的是一個lazy,寫了200行代碼,好不容易把樣例過了,結果wa。。。瞟了一眼別人的博客,發現大多數是用兩個lazy標記,我那時候想到是我lazy這地方有缺陷,我也不想 用兩個lazy,一來是麻煩,二來是我根本想不到爲什麼用兩個lazy,套用別人的東西,下次 也 不會做。。就醬紫,調試了半天終於ac了。但我還有個問題,就是題目中的數據是100000個,我開110000都會re,果斷開了2*1e6過了。但還是搞不清楚原因,大家指點下。本人寫的代碼太搓了。。以後也要多向大神們學習
#include <iostream>
#include<stdio.h>
#include<algorithm>
#include<cstring>
using namespace std;
const int MAX=1e5*2;
int d[MAX],m,n,i,a,b,f,T;
typedef struct P
{
    int lnum_0,rnum_0,mnum_0,snum;
    int lnum_1,rnum_1,mnum_1;
    int left,right,cover;
    void set_0(int len)
    {
        lnum_0=mnum_0=rnum_0=len;
    }
    void set_1(int len)
    {
        lnum_1=mnum_1=rnum_1=len;
    }
    void fun(int f)
    {
        int len=right-left+1;
        if(f==0)
        {
            set_0(len); set_1(0); snum=0;
            cover=f;
        }
        if(f==1)
        {
            set_0(0); set_1(len); snum=len;
            cover=f;
        }
        if(f==2)
        {
            int co=cover;
            swap( lnum_0, lnum_1);
            swap( rnum_0, rnum_1);
            swap( mnum_0, mnum_1);
            snum=len-snum;
            if(co==-1)
                cover=2;
            if(co==0)
                cover=1;
            if(co==1)
                cover=0;
            if(co==2)
                cover=-1;
        }
    }
}P;
P p[4*MAX];
void pushup(int k)
{
    int lt=k<<1,rt=lt+1,llen=p[lt].right-p[lt].left+1,rlen=p[rt].right-p[rt].left+1;
    p[k].snum=p[lt].snum+p[rt].snum;
    //0有關數據合併
    if(p[lt].lnum_0==llen)
        p[k].lnum_0=llen+p[rt].lnum_0;
    else
        p[k].lnum_0=p[lt].lnum_0;
    if(p[rt].rnum_0==rlen)
        p[k].rnum_0=rlen+p[lt].rnum_0;
    else
        p[k].rnum_0=p[rt].rnum_0;
    p[k].mnum_0=max(max(p[lt].mnum_0,p[rt].mnum_0),p[lt].rnum_0+p[rt].lnum_0);
    //1有關數據合併
    if(p[lt].lnum_1==llen)
        p[k].lnum_1=llen+p[rt].lnum_1;
    else
        p[k].lnum_1=p[lt].lnum_1;

    if(p[rt].rnum_1==rlen)
        p[k].rnum_1=rlen+p[lt].rnum_1;
    else
        p[k].rnum_1=p[rt].rnum_1;
    p[k].mnum_1=max(max(p[lt].mnum_1,p[rt].mnum_1),p[lt].rnum_1+p[rt].lnum_1);
}
void pushdown(int k)
{
    if(p[k].cover!=-1)
    {
        int lt=k<<1,rt=lt+1,llen=p[lt].right-p[lt].left+1,rlen=p[rt].right-p[rt].left+1;
        int f= p[k].cover;
        p[lt].fun(f);
        p[rt].fun(f);
        p[k].cover=-1;
    }
}
void build(int k,int l,int r)
{
    p[k].left=l; p[k].right=r; p[k].cover=-1;//cout<<"k= "<<k<<endl;
    if(l==r)
    {
        p[k].lnum_0= p[k].rnum_0= p[k].mnum_0=d[r]?0:1;
        p[k].lnum_1= p[k].rnum_1= p[k].mnum_1=d[r]?1:0;
        p[k].snum=d[r];
        return;
    }
    int lt=k<<1,rt=lt+1,mid=(l+r)>>1;
    build(lt,l,mid);
    build(rt,mid+1,r);
    pushup(k);
}
void update(int k,int s,int e,int f)
{
    if( p[k].left==s&& p[k].right==e)
    {
        int co= p[k].cover;
        if(f<2)
        {
            p[k].lnum_0= p[k].rnum_0 =p[k].mnum_0=f?0:e-s+1;
            p[k].snum=p[k].lnum_1= p[k].rnum_1 =p[k].mnum_1=f?e-s+1:0;
            p[k].cover=f;
        }
        if(f==2)
            p[k].fun(2);
        return;
    }
    pushdown(k);
    int lt=k<<1,rt=lt+1,mid= (p[k].left+ p[k].right)>>1;
    if(e<=mid)
        update(lt,s,e,f);
    else
        if(s>mid)
        update(rt,s,e,f);
    else
    {
        update(lt,s,mid,f);
        update(rt,mid+1,e,f);
    }
    pushup(k);
}
int query(int k,int s,int e,int f)
{
    pushdown(k);
    int mid=( p[k].left +p[k].right)>>1,lt=k<<1,rt=lt+1;
    if( p[k].left==s && p[k].right==e)
    {
        if(f==3)
            return  p[k].snum;
        else
            return  p[k].mnum_1;
    }
    if(mid>=e)
            return query(lt,s,e,f);
        else
            if(mid<s)
            return query(rt,s,e,f);
    else
    {
        int temp1=query(lt,s,mid,f),temp2=query(rt,mid+1,e,f);
        if(f==3)
            return temp1+temp2;
        else
        {
            int lm=min(mid-s+1, p[lt].rnum_1),rm=min(e-mid, p[rt].lnum_1);
            return max(max(temp1,temp2),lm+rm);
        }
    }

}
int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(i=0;i<n;i++)
            scanf("%d",d+i);
        build(1,0,n-1);
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&f,&a,&b);
            if(f<=2)
                update(1,a,b,f);
            else
            {
                int mm=query(1,a,b,f);
                printf("%d\n",mm);
            }
        }
    }
    return 0;
}

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