zoukankan      html  css  js  c++  java
  • HDU5997 【线段树】

    思路:

    用vector存一下各种颜色的区间,每次处理颜色的区间,相同颜色不需要更新。区间最多1e6个没错,但是随着颜色的更替区间只会越来越少。

    维护区间左右两端的颜色,lazy一下。

    区间合并的时候 sum= sum_left + sum_right , 如果左儿子的区间右边和右儿子的区间左边颜色相同 sum--。

    复杂度:don't know;

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+10;
    
    struct Seg{
        int Sum;
        int Lazy;
        int Left,Right;
        int Left_Color,Right_Color;
    }q[N*4];
    
    struct asd{
        int Left,Right;
    };
    vector<asd>eg[1000000+10];
    int col[N];
    
    void Pushdown(int num)
    {
        if(q[num].Lazy==-1) return;
        q[num<<1].Lazy=q[num<<1|1].Lazy=q[num].Lazy;
        q[num<<1].Sum=q[num<<1|1].Sum=1;
        q[num<<1].Left_Color=q[num<<1].Right_Color=q[num].Lazy;
        q[num<<1|1].Left_Color=q[num<<1|1].Right_Color=q[num].Lazy;
        q[num].Lazy=-1;
    }
    
    void Build(int num,int Left,int Right)
    {
        q[num].Left=Left;q[num].Right=Right;q[num].Lazy=-1;
        if(Left == Right){
            q[num].Sum=1;
            q[num].Left_Color=q[num].Right_Color=col[Left];
            return;
        }
        int Mid=(Left+Right)>>1;
        Build(num<<1,Left,Mid);
        Build(num<<1|1,Mid+1,Right);
        q[num].Left_Color=q[num<<1].Left_Color;
        q[num].Right_Color=q[num<<1|1].Right_Color;
        if(q[num<<1].Right_Color == q[num<<1|1].Left_Color)
            q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum-1;
        else
            q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum;
    }
    
    int Query(int num,int Left,int Right)
    {
        if(q[num].Left>=Left && q[num].Right<=Right) return q[num].Sum;
        Pushdown(num);
    
        int Mid=(q[num].Left+q[num].Right)>>1;
        if(Mid>=Right)
            return Query(num<<1,Left,Right);
        else if(Mid<Left)
            return Query(num<<1|1,Left,Right);
        else{
            int ans=0;
            ans+=Query(num<<1,Left,Mid);
            ans+=Query(num<<1|1,Mid+1,Right);
            if(q[num<<1].Right_Color == q[num<<1|1].Left_Color) ans--;
            return ans;
        }
    }
    
    void Update(int num,int Left,int Right,int Color)
    {
        if(Left<=q[num].Left && q[num].Right<=Right){
            q[num].Lazy=Color;
            q[num].Sum=1;
            q[num].Left_Color=q[num].Right_Color=Color;
            return;
        }
        Pushdown(num);
    
        int Mid=(q[num].Left+q[num].Right)>>1;
        if(Mid>=Right)
            Update(num<<1,Left,Right,Color);
        else if(Mid<Left)
            Update(num<<1|1,Left,Right,Color);
        else
        {
            Update(num<<1,Left,Mid,Color);
            Update(num<<1|1,Mid+1,Right,Color);
        }
        q[num].Left_Color=q[num<<1].Left_Color;
        q[num].Right_Color=q[num<<1|1].Right_Color;
        q[num].Sum=q[num<<1].Sum+q[num<<1|1].Sum;
        if(q[num<<1].Right_Color == q[num<<1|1].Left_Color) q[num].Sum--;
    }
    
    void init(int n)
    {
        for(int i=0;i<=1000000;i++)
            eg[i].clear();
    
        asd temp;
        int Color,Pre_Color=-1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&Color);
            col[i]=Color;
            if(Pre_Color==-1){
                temp.Left=i;
                Pre_Color=Color;
            }
            else if(Pre_Color!=Color){
                temp.Right=i-1;
                eg[Pre_Color].push_back(temp);
                temp.Left=i;
                Pre_Color=Color;
            }
        }
        temp.Right=n;
        eg[Pre_Color].push_back(temp);
    
        Build(1,1,n);
    }
    
    void solve(int n)
    {
        asd temp;
        int Left,Right,x,y;
        int op;
        while(n--)
        {
            scanf("%d",&op);
            if(op==1)
            {
                scanf("%d%d",&x,&y);
                if(x==y) continue;
    
                int sz=eg[x].size();
                for(int i=0;i<sz;i++)
                {
                    temp=eg[x][i];
                    Update(1,temp.Left,temp.Right,y);
                    eg[y].push_back(eg[x][i]);
                }
                eg[x].clear();
            }
            else
            {
                scanf("%d%d",&Left,&Right);
                printf("%d
    ",Query(1,Left,Right));
            }
        }
    }
    
    int main()
    {
        int n,T,Q;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&Q);
            init(n);
            solve(Q);
        }
        return 0;
    }
    


  • 相关阅读:
    VS生成事件时复制文件到指定位置
    Windows服务BAT命令-安装、卸载、启动、停止
    Lambda表达式动态组装查询条件
    动软模板使用流程
    使用jquery.qrcode生成二维码
    MySQL报错:Packets larger than max_allowed_packet are not all
    Excel操作之VLOOKUP函数
    Visual Studio 编辑器打开项目后,一直提醒Vs在忙,解决方法
    使用BaiDu Java Script Web Api 在Web开发中嵌入地图使用步骤
    C#或Net连接Oracle操作提示 Oracle 客户端 version 8.1.7 或更高版本报错
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6777487.html
Copyright © 2011-2022 走看看