帶lazy標記的線段樹


線段樹的lazy操作

POJ 2777 Count Color為例。

線段樹,是一個滿的二叉樹,每次每一個子節點都是父節點的一半。所以二叉樹的每個節點都維護了一個區間。可是實現快速的查詢。
對於更新來講的話,如果每次都更新到最下面的節點,會非常的耗時間。所以假如更新到某個節點的時候,而這個節點的左右段和要更新的最有端點一致的話,就可以僅更新該節點,並在他的子節點上面(兩個)加上一個lazy-tag,不再往子節點更新值。如果以后更新到加lazy-tag標記的結點時,則需要把這個標記的值更新下去,並且在他的子節點跟新lazy-tag標記,並取消這個節點的lazy-tag

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<set>
#include<queue>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
#define inf 0x3f3f3f
#define MAXN 100100

struct tree
{
    int l;
    int r;
    int colr;
    bool lazy;//lazy是lazy-tag
};
tree t[MAXN*4];
int L,T,O;
int cc;
int x,y,c;
void Swap()
{
    int temp=x;
    x=y;
    y=temp;
}
void Build(int l,int r,int index)
{
    t[index].l=l;
    t[index].r=r;
    t[index].colr=1;
    t[index].lazy=0;//lazy=0,說明當前結點沒有lazy標記。
    if(l==r)
        return;
    int mid=(l+r)>>1;
    Build(l,mid,index<<1);
    Build(mid+1,r,index<<1|1);
}
void inse(int l,int r,int index,int cl)
{
    if(t[index].l==l && t[index].r==r)
    {
        t[index].colr=(1<<(cl-1));
        t[index].lazy=1;//更新到相應節點的時候,加上lazy-tag
        return;
    }
    if(t[index].lazy) //如果當前的節點有lazy標記,則
    {
        t[index].lazy=0;//1,需要取消lazy標記,
        t[index<<1].lazy=1;//2,往子節點傳遞lazy標記
        t[index<<1|1].lazy=1;
        t[index<<1].colr=t[index].colr;//3,並傳遞值
        t[index<<1|1].colr=t[index].colr;
    }
    int mid=(t[index].l+t[index].r)>>1;
    if(r<=mid)
        inse(l,r,index<<1,cl);
    else if(l>mid)
        inse(l,r,index<<1|1,cl);
    else
    {
        inse(l,mid,index<<1,cl);
        inse(mid+1,r,index<<1|1,cl);
    }
    t[index].colr=t[index<<1].colr | t[index<<1|1].colr;//往上更新值。
}
void quer(int l,int r,int index)
{
	//如果遇見帶lazy標記的節點,只需要返回當前的節點的值就行了,
    if(t[index].lazy || (t[index].l==l && t[index].r==r) )
    {
        cc|=t[index].colr;
        return;
    }
    int mid=(t[index].l+t[index].r)>>1;
    if(r<=mid)
        quer(l,r,index<<1);
    else if(l>mid)
        quer(l,r,index<<1|1);
    else
    {
        quer(l,mid,index<<1);
        quer(mid+1,r,index<<1|1);
    }
}
int main()
{
    while(scanf("%d%d%d",&L,&T,&O)!=EOF)
    {
        char ss;
        Build(1,L,1);
        while(O--)
        {

            scanf(" %c",&ss);
            if(ss=='C')
            {
                scanf("%d%d%d",&x,&y,&c);
                if(x>y)
                    Swap();
                inse(x,y,1,c);
            }
            else
            {
                int ans=0;
                scanf("%d%d",&x,&y);
                if(x>y)
                    Swap();

                cc=0;
                quer(x,y,1);
                for(int i=0; i<T; i++)
                {
                    if(cc&(1<<i))
                        ans++;
                }
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM