• 带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
    ",ans);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    由sqlite3入门数据库学习
    Python"八荣八耻"
    Mysql数据导出-Ubuntu
    python-open-cv 自动人脸识别安装包
    Pymysql mysqllient 那些问题!
    MySQL查询(未完结)
    Scarpy+selenium 结合使用
    Scrapy框架的使用 -- 自动跳转链接并请求
    Scrapy框架的使用
    MySQL基础
  • 原文地址:https://www.cnblogs.com/zzulipomelo/p/5361709.html
Copyright © 2020-2023  润新知