zoukankan      html  css  js  c++  java
  • 洛谷 P2486 [SDOI2011]染色/bzoj 2243: [SDOI2011]染色 解题报告

    [SDOI2011]染色

    题目描述

    给定一棵有n个节点的无根树和m个操作,操作有2类:
    1、将节点a到节点b路径上所有点都染成颜色c;
    2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
    如“112221”由3段组成:“11”、“222”和“1”。
    请你写一个程序依次完成这m个操作。

    输入输出格式

    输入格式

    第一行包含2个整数n和m,分别表示节点数和操作数;
    第二行包含n个正整数表示n个节点的初始颜色
    下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。
    下面 行每行描述一个操作:
    “C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
    “Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

    输出格式

    对于每个询问操作,输出一行答案。

    说明

    数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。


    本来想复习一下树剖的,谁知道这题打起来超恶心。。

    线段树上维护一下区间左端点颜色和右端点颜色,多的减掉就行啦


    Code:

    #include <cstdio>
    #define ls id<<1
    #define rs id<<1|1
    int min(int x,int y){return x<y?x:y;}
    int max(int x,int y){return x>y?x:y;}
    const int N=2e5+10;
    int head[N],to[N],Next[N],cnt;
    void add(int u,int v)
    {
        to[++cnt]=v;Next[cnt]=head[u];head[u]=cnt;
    }
    int top[N],dep[N],siz[N],f[N],dfn[N],ws[N],ha[N],dfs_clock,n,m;
    void dfs1(int now)
    {
        ++siz[now];
        for(int i=head[now];i;i=Next[i])
        {
            int v=to[i];
            if(f[now]!=v)
            {
                dep[v]=dep[now]+1;
                f[v]=now;
                dfs1(v);
                siz[now]+=siz[v];
                if(siz[ws[now]]<siz[v])
                    ws[now]=v;
            }
        }
    }
    void dfs2(int now,int anc)
    {
        dfn[now]=++dfs_clock;
        ha[dfs_clock]=now;
        top[now]=anc;
        if(ws[now]) dfs2(ws[now],anc);
        for(int i=head[now];i;i=Next[i])
            if(!dfn[to[i]])
                dfs2(to[i],to[i]);
    }
    int clo[N],lc[N<<2],rc[N<<2],sum[N<<2],lazy[N<<2];
    void updata(int id)//保证不为叶子
    {
        sum[id]=sum[ls]+sum[rs]-(rc[ls]==lc[rs]);
        lc[id]=lc[ls];
        rc[id]=rc[rs];
    }
    void build(int id,int l,int r)
    {
        if(l==r)
        {
            lc[id]=rc[id]=clo[ha[l]];
            sum[id]=1;
            return;
        }
        int mid=l+r>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
        updata(id);
    }
    void pushdown(int id)//保证不为叶子
    {
        if(lazy[id])
        {
            lazy[ls]=lazy[rs]=lc[ls]=lc[rs]=rc[ls]=rc[rs]=lazy[id];
            sum[ls]=sum[rs]=1;
            lazy[id]=0;
        }
    }
    int line=0;
    void change(int id,int l,int r,int L,int R,int color)
    {
        if(L!=R) pushdown(id);
        if(l==L&&r==R)
        {
            lazy[id]=lc[id]=rc[id]=color;
            sum[id]=1;
            return;
        }
        int Mid=L+R>>1;
        if(r<=Mid) change(ls,l,r,L,Mid,color);
        else if(l>Mid) change(rs,l,r,Mid+1,R,color);
        else change(ls,l,Mid,L,Mid,color),change(rs,Mid+1,r,Mid+1,R,color);
        updata(id);
    }
    int query(int id,int l,int r,int L,int R,int &cl,int &cr)
    {
        if(L!=R) pushdown(id);
        if(l==L&&r==R)
        {
            cl=lc[id],cr=rc[id];
            return sum[id];
        }
        int Mid=L+R>>1,c0,c1;
        if(r<=Mid) return query(ls,l,r,L,Mid,cl,cr);
        else if(l>Mid) return query(rs,l,r,Mid+1,R,cl,cr);
        else return query(ls,l,Mid,L,Mid,cl,c0)+query(rs,Mid+1,r,Mid+1,R,c1,cr)-(rc[ls]==lc[rs]);
    }
    void t_change(int x,int y,int c)
    {
        while(top[x]!=top[y])
        {
            if(dep[top[x]]>dep[top[y]])
            {
                change(1,dfn[top[x]],dfn[x],1,n,c);
                x=f[top[x]];
            }
            else
            {
                change(1,dfn[top[y]],dfn[y],1,n,c);
                y=f[top[y]];
            }
        }
        change(1,min(dfn[x],dfn[y]),max(dfn[x],dfn[y]),1,n,c);
    }
    int t_query(int x,int y)
    {
        int s=0,xc=0,yc=0,cl,cr;
        while(top[x]!=top[y])
        {
            if(dep[top[x]]>dep[top[y]])
            {
                s+=query(1,dfn[top[x]],dfn[x],1,n,cl,cr);
                s-=cr==xc;
                xc=cl;
                x=f[top[x]];
            }
            else
            {
                s+=query(1,dfn[top[y]],dfn[y],1,n,cl,cr);
                s-=cr==yc;
                yc=cl;
                y=f[top[y]];
            }
        }
        s+=query(1,min(dfn[x],dfn[y]),max(dfn[x],dfn[y]),1,n,cl,cr);
        if(dfn[x]<dfn[y]) s-=(cl==xc)+(cr==yc);
        else s-=(cl==yc)+(cr==xc);
        return s;
    }
    int main()
    {
        //freopen("data.in","r",stdin);
        //freopen("data.out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",clo+i);
        for(int u,v,i=1;i<n;i++)
        {
            scanf("%d%d",&u,&v);
            add(u,v),add(v,u);
        }
        dfs1(1),dfs2(1,1);
        build(1,1,n);
        char op[21];
        for(int a,b,c,i=1;i<=m;i++)
        {
            scanf("%s%d%d",op,&a,&b);
            if(op[0]=='C') scanf("%d",&c),t_change(a,b,c);
            else printf("%d
    ",t_query(a,b));
        }
        return 0;
    }
    
    

    2018.8.27

  • 相关阅读:
    js静态成员和实例成员
    js构造函数
    js创建对象
    js演示面向对象
    JavaScript特点
    像素鸟游戏
    图片瀑布流
    微信聊天模拟
    飞机游戏动画特效
    SpringBoot 核心理论
  • 原文地址:https://www.cnblogs.com/butterflydew/p/9544483.html
Copyright © 2011-2022 走看看