zoukankan      html  css  js  c++  java
  • BZOJ 2243: [SDOI2011]染色

    Description

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

    Input

    第一行包含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)路径上的颜色段数量。

    Output

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

    Sample Input

    6 5
    2 2 1 2 1 1
    1 2
    1 3
    2 4
    2 5
    2 6
    Q 3 5
    C 2 1 1
    Q 3 5
    C 5 1 2
    Q 3 5

    Sample Output

    3
    1
    2

    HINT

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

    Source

    第一轮day1

    首先用树剖和线段树处理

    这时线段树记录的信息有a[x].l表示这段区间最左边的颜色编号,a[x].r表示这段区间最右边的颜色编号,a[x].s表示颜色数

    在push up的时候,a[x].s=a[ls].s+a[rs].s,如果a[ls].r==a[rs].l就说明重复计入了一个,那么就要讲a[x].s--;

    在查询答案时也要注意这一点,对于分别查询的两个区间之间要进行颜色是否相同的判断,对于链与链之间也要进行相同的判断。

    #include<cstdio>
    #include<algorithm>
    #define ls x<<1
    #define rs x<<1|1
    using namespace std;
    const int N=1e5+5;
    struct Y
    {
        int v,f,n;
    }y[N<<1];
    struct A
    {
        int l,r,s,lz;
        void fz(int g)
        {
            l=r=lz=g;
            s=1;
        }
    }a[N<<2];
    int s,ss,siz[N],fa[N],co[N],dfn[N],tou[N],hson[N],n;
    void add(int u,int v)
    {
        y[++s].v=v;
        y[s].n=y[u].f;
        y[u].f=s;
    }
    void dfs1(int u)
    {
        siz[u]=1;
        for(int i=y[u].f;i;i=y[i].n)
            if(y[i].v!=fa[u])
            {
                fa[y[i].v]=u;
                dfs1(y[i].v);
                siz[u]+=siz[y[i].v];
                if(siz[y[i].v]>siz[hson[u]]) hson[u]=y[i].v;
            }
    }
    void dfs2(int u,int to)
    {
        dfn[u]=++ss;
        tou[u]=to;
        if(hson[u]) dfs2(hson[u],to);
        for(int i=y[u].f;i;i=y[i].n)
            if(y[i].v!=hson[u]&&y[i].v!=fa[u]) dfs2(y[i].v,y[i].v);
    }
    void pd(int x,int l,int r,int mid)
    {
        if(a[x].lz)
        {
            a[ls].fz(a[x].lz),a[rs].fz(a[x].lz);
            a[x].lz=0;
        }
    }
    void chan(int x,int l,int r,int ql,int qr,int z)
    {
        if(ql<=l&&r<=qr) a[x].fz(z);
        else
        {
            int mid=(l+r)>>1;
            pd(x,l,r,mid);
            if(ql<=mid) chan(ls,l,mid,ql,qr,z);
            if(qr>mid) chan(rs,mid+1,r,ql,qr,z);
            a[x].l=a[ls].l;a[x].r=a[rs].r;
            a[x].s=a[ls].s+a[rs].s;
            if(a[ls].r==a[rs].l) --a[x].s;
        }
    }
    int askk(int x,int l,int r,int ql,int qr)
    {
        if(ql<=l&&r<=qr) return a[x].s;
        int mid=(l+r)>>1,re=0;
        pd(x,l,r,mid);
        if(ql<=mid) re+=askk(ls,l,mid,ql,qr);
        if(qr>mid) re+=askk(rs,mid+1,r,ql,qr);
        if(ql<=mid&&qr>mid&&a[ls].r==a[rs].l) --re;
        return re;
    }
    int gc(int x,int l,int r,int wz)
    {
        if(l==r) return a[x].lz;
        int mid=(l+r)>>1;
        pd(x,l,r,mid);
        if(wz<=mid) return gc(ls,l,mid,wz);
        else return gc(rs,mid+1,r,wz);
    }
    int qu(int u,int v)
    {
        int re=0;
        while(tou[u]!=tou[v])
        {
            if(dfn[u]<dfn[v]) swap(u,v);
            re+=askk(1,1,n,dfn[tou[u]],dfn[u]);
            if(gc(1,1,n,dfn[tou[u]])==gc(1,1,n,dfn[fa[tou[u]]])) --re;
            u=fa[tou[u]];
        }
        if(dfn[u]<dfn[v]) swap(u,v);
        re+=askk(1,1,n,dfn[v],dfn[u]);
        return re;
    }
    int main()
    {
        int m,u,v;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;++i) scanf("%d",&co[i]);
        for(int i=2;i<=n;++i)
        {
            scanf("%d%d",&u,&v);
            add(u,v),add(v,u);
        }
        dfs1(1);
        dfs2(1,1);
        for(int i=1;i<=n;++i)
            chan(1,1,n,dfn[i],dfn[i],co[i]+1);
        while(m--)
        {
            char c[5];
            int cc;
            scanf("%s%d%d",c,&u,&v);
            if(c[0]=='Q') printf("%d
    ",qu(u,v));
            else
            {
                scanf("%d",&cc);++cc;
                while(tou[u]!=tou[v])
                {
                    if(dfn[u]<dfn[v]) swap(u,v);
                    chan(1,1,n,dfn[tou[u]],dfn[u],cc);
                    u=fa[tou[u]];
                }
                if(dfn[u]<dfn[v]) swap(u,v);
                chan(1,1,n,dfn[v],dfn[u],cc);
            }
        }
        return 0;
    }
  • 相关阅读:
    修改boot.ini产生彩色的启动菜单
    五行山下的猴子
    一个中文输入的类
    黑洞
    驱动中 定时
    水煮TCPMP (转)
    OGame的建筑说明
    3D数学 矩阵的更多知识(1)
    OGame银河系说明
    七则很有启迪性的心理寓言【转】
  • 原文地址:https://www.cnblogs.com/bzmd/p/9410945.html
Copyright © 2011-2022 走看看