• POJ2777 线段树区间染色问题


     

    题意:给L长度的木板,给T种颜色,给O个操作,每次可以选择一段区间染色,或查询一个区间的颜色种类

    思路1:用叶节点存具体颜色,父节点记录子节点的颜色集合(都采用二进制从低位到高位表示具体颜色数字)

    #include <iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    
    const int maxn=1e5+10;
    int l,t,o;
    struct note
    {
        int left,right,sum,lazy;
        void up(int val)
        {
            sum=1<<(val-1);
            lazy=val;
        }
    } tree[maxn*4];
    void pushup(int id)
    {
        tree[id].sum=tree[id<<1].sum|tree[id<<1|1].sum;
    }
    void pushdown(int id)
    {
        if(tree[id].lazy)
        {
            tree[id<<1].up(tree[id].lazy);
            tree[id<<1|1].up(tree[id].lazy);
            tree[id].lazy=0;
        }
    }
    
    void build(int id,int l,int r)
    {
        tree[id].left=l;
        tree[id].right=r;
        if(l==r)
            tree[id].sum=1;
        else
        {
            int mid=(l+r)/2;
            build(id<<1,l,mid);
            build(id<<1|1,mid+1,r);
            pushup(id);
        }
    }
    int query(int id,int l,int r)
    {
        if(l<=tree[id].left&&tree[id].right<=r)
            return tree[id].sum;
        pushdown(id);
        int mid=(tree[id].left+tree[id].right)/2;
        int ans=0;
        if(l<=mid) ans|=query(id<<1,l,r);
        if(r>mid) ans|=query(id<<1|1,l,r);
        return ans;
    }
    
    void update(int id,int l,int r,int val)
    {
        if(l<=tree[id].left&&tree[id].right<=r)
        {
            tree[id].up(val);
            return;
        }
        pushdown(id);
        int mid=(tree[id].left+tree[id].right)/2;
        if(l<=mid) update(id<<1,l,r,val);
        if(r>mid) update(id<<1|1,l,r,val);
        pushup(id);
    }
    
    int main()
    {
        int l,t,o;
        scanf("%d%d%d",&l,&t,&o);
        build(1,1,l);
        for(int i=1; i<=o; i++)
        {
            getchar();
            char op;
            scanf("%c",&op);
            if(op=='C')
            {
                int l,r,val;
                if(l>r)
                    swap(l,r);
                scanf("%d%d%d",&l,&r,&val);
                update(1,l,r,val);
            }
            else
            {
                int l,r;
                scanf("%d%d",&l,&r);
                if(l>r)
                    swap(l,r);
                int sum=query(1,l,r);
                int ans=0;
                while(sum>0)
                {
                    if(sum&1) ans++;
                    sum=sum>>1;
                }
                printf("%d
    ",ans);
            }
        }
    }

    思路2:用线段树叶节点记录颜色所代表的数字,父节点为-1表示两个子节点颜色不相同,>0时的数字代表子节点全为这个数字对应颜色。

    #include <iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    
    const int maxn=1e5+10;
    int a[maxn];
    int l,t,o;
    int vis[35];
    struct note
    {
        int left,right,sum,lazy;
        void up(int val)
        {
            sum=val;
            lazy=val;
        }
    } tree[maxn*4];
    void pushup(int id)
    {
        if(tree[id<<1].sum==-1||tree[id<<1|1].sum==-1)
            tree[id].sum=-1;
        else if(tree[id<<1].sum==tree[id<<1|1].sum)
            tree[id].sum=tree[id<<1].sum;
        else
            tree[id].sum=-1;
    }
    void pushdown(int id)
    {
        if(tree[id].lazy)
        {
            tree[id<<1].up(tree[id].lazy);
            tree[id<<1|1].up(tree[id].lazy);
            tree[id].lazy=0;
        }
    }
    
    void build(int id,int l,int r)
    {
        tree[id].left=l;
        tree[id].right=r;
        if(l==r)
            tree[id].sum=1;
        else
        {
            int mid=(l+r)/2;
            build(id<<1,l,mid);
            build(id<<1|1,mid+1,r);
            pushup(id);
        }
    }
    void query(int id,int l,int r)
    {
        if(tree[id].sum!=-1)
        {
            vis[tree[id].sum]=1;
            return;
        }
    //    pushdown(id);
        int mid=(tree[id].left+tree[id].right)/2;
        if(l<=mid) query(id<<1,l,r);
        if(r>mid) query(id<<1|1,l,r);
    }
    void update(int id,int l,int r,int val)
    {
        if(l<=tree[id].left&&tree[id].right<=r)
        {
            tree[id].up(val);
            return;
        }
        pushdown(id);
        int mid=(tree[id].left+tree[id].right)/2;
        if(l<=mid) update(id<<1,l,r,val);
        if(r>mid) update(id<<1|1,l,r,val);
        pushup(id);
    }
    
    
    int main()
    {
        scanf("%d%d%d",&l,&t,&o);
        build(1,1,l);
        for(int i=1; i<=o; i++)
        {
            char op;
            getchar();
            scanf("%c",&op);
            if(op=='C')
            {
                int l,r,color;
                scanf("%d%d%d",&l,&r,&color);
                update(1,l,r,color);
            }
            else
            {
                int l,r;
                scanf("%d%d",&l,&r);
                memset(vis,0,sizeof(vis));
                query(1,l,r);
                int ans=0;
                for(int i=1; i<=30; i++)
                {
                    if(vis[i])
                        ans++;
                }
                printf("%d
    ",ans);
            }
        }
    }
  • 相关阅读:
    Hibernate使用固定值关联表
    使用spring-data-JPA调用存储过程
    angularjs动态添加节点时,绑定到$scope中
    JPA子查询
    表格表头固定的一种实现方式
    Unicode、UTF8与UTF16
    primefaces4.0基本教程以及增删改查
    tomcat发布webservice
    KonBoot – 只要5K映象文件轻易绕过您的WindowsXP/VISTA/7系统的密码
    Setting .xap MIME Type for Silverlight
  • 原文地址:https://www.cnblogs.com/dongdong25800/p/11620054.html
Copyright © 2020-2023  润新知