//Accepted    18440 KB    5556 ms
/*
    source:HYSBZ 2243
    time  :2015.5.29
    by    :songt
  */
/*题解:
树链剖分

  */

#include <cstdio>
#include <cstring>

;
struct Edge
{
    int u,v;
    Edge(){}
    Edge(int u,int v):u(u),v(v){}
}edge[*imax_n];
int head[imax_n];
*imax_n];
int tot;
int top[imax_n];
int son[imax_n];
int num[imax_n];
int p[imax_n];
int fp[imax_n];
int deep[imax_n];
int fa[imax_n];
int pos;

void init()
{
    memset(head,-,sizeof(head));
    memset(next,-,sizeof(next));
    tot=;
    memset(son,-,sizeof(son));
    pos=;
}

void addEdge(int u,int v)
{
    edge[tot]=Edge(u,v);
    next[tot]=head[u];
    head[u]=tot++;
}

void dfs1(int u)
{
    num[u]=;
    ;i=next[i])
    {
        int v=edge[i].v;
        if (v!=fa[u])
        {
            fa[v]=u;
            deep[v]=deep[u]+;
            dfs1(v);
            num[u]+=num[v];
             || num[son[u]]<num[v])
                son[u]=v;
        }
    }
}

void dfs2(int u)
{
    p[u]=pos++;
    fp[p[u]]=u;
    ) return ;
    top[son[u]]=top[u];
    dfs2(son[u]);
    ;i=next[i])
    {
        int v=edge[i].v;
        if (v!=son[u] && v!=fa[u])
        {
            dfs2(top[v]=v);
        }
    }
}

struct Tree
{
    int l,r;
    int lc,rc;
    int num;
    int same;
    int color;
}f[imax_n*];
int color[imax_n];

void push_down(int t)
{
    f[*t].same=f[*t+].same=;
    f[*t].color=f[*t+].color=f[t].color;
    f[*t].num=f[*t+].num=;
    f[*t].lc=f[*t].rc=f[t].color;
    f[*t+].lc=f[*t+].rc=f[t].color;
    f[t].same=;
}

void push_up(int t)
{
    f[t].num=f[*t].num+f[*t+].num-(f[*t].rc==f[*t+].lc);
    f[t].lc=f[*t].lc;
    f[t].rc=f[*t+].rc;
}

void build(int t,int l,int r)
{
    f[t].l=l;
    f[t].r=r;
    f[t].same=;
    if (l==r)
    {
        f[t].lc=f[t].rc=color[fp[l]];
        f[t].color=color[fp[l]];
        f[t].num=;
        f[t].same=;
        return ;
    }
    ;
    build(*t,l,mid);
    build(*t+,mid+,r);
    push_up(t);
}

void update(int t,int l,int r,int color)
{
    if (f[t].l==l && f[t].r==r)
    {
        f[t].color=color;
        f[t].num=;
        f[t].lc=f[t].rc=color;
        f[t].same=;
        return ;
    }
    if (f[t].same) push_down(t);
    ;
    *t,l,r,color);
    else
    {
        *t+,l,r,color);
        else
        {
            update(*t,l,mid,color);
            update(*t+,mid+,r,color);
        }
    }
    push_up(t);
}

int query(int t,int l,int r,int &cl,int &rl)
{
    if (f[t].l==l && f[t].r==r)
    {
        cl=f[t].lc;
        rl=f[t].rc;
        return f[t].num;
    }
    if (f[t].same) push_down(t);
    ;
    *t,l,r,cl,rl);
    else
    {
        *t+,l,r,cl,rl);
        else
        {
            int lcl,lcr,rcl,rcr;
            int numl,numr;
            numl=query(*t,l,mid,lcl,lcr);
            numr=query(*t+,mid+,r,rcl,rcr);
            cl=lcl;
            rl=rcr;
            return numl+numr-(lcr==rcl);
        }
    }
}

void swap(int &a,int &b)
{
    int t=a;
    a=b;
    b=t;
}

void OpC(int u,int v,int c)
{
    int f1=top[u],f2=top[v];
    while (f1!=f2)
    {
        //printf("u=%d v=%d top[u]=%d top[v]=%d\n",u,v,f1,f2);
        if (deep[f1]<deep[f2])
        {
            swap(f1,f2);
            swap(u,v);
        }
        update(,p[f1],p[u],c);
        //printf("update %d %d\n",f1,u);
        u=fa[f1];
        f1=top[u];
    }
    if (deep[u]>deep[v]) swap(u,v);
    update(,p[u],p[v],c);
    //printf("update %d %d\n",u,v);
}

int OpQ(int u,int v)
{
    int f1=top[u],f2=top[v];
    ,cv=-;
    ;
    int lc,rc;
    while (f1!=f2)
    {
        if (deep[f1]<deep[f2])
        {
            swap(f1,f2);
            swap(u,v);
            swap(cu,cv);
        }
        ,p[f1],p[u],lc,rc);
        //printf("%d %d num=%d lc=%d rc=%d\n",f1,u,tmp,lc,rc);
        ans+=tmp;
        ans-=(cu==rc);
        cu=lc;
        u=fa[f1];
        f1=top[u];
    }
    if (deep[u]>deep[v])
    {
        swap(u,v);
        swap(cu,cv);
    }
    ,p[u],p[v],lc,rc);
    //printf("%d %d num=%d lc=%d rc=%d\n",u,v,tmp,lc,rc);
    ans+=query(,p[u],p[v],lc,rc);
    ans-=(cu==lc);
    ans-=(cv==rc);
    return ans;
}

int n,m;
];
int u,v,c;

int main()
{
    //while (scanf("%d%d",&n,&m)==2)
    scanf("%d%d",&n,&m);
    {
        init();
        ;i<=n;i++)
        {
            scanf("%d",&color[i]);
        }
        ;i<n-;i++)
        {
            scanf("%d%d",&u,&v);
            addEdge(u,v);
            addEdge(v,u);
        }
        fa[]=;
        deep[]=;
        dfs1();
        dfs2(top[]=);
        build(,,pos-);
        ;i<m;i++)
        {
            scanf("%s",op);
            ]=='Q')
            {
                scanf("%d%d",&u,&v);
                printf("%d\n",OpQ(u,v));
            }
            else
            {
                scanf("%d%d%d",&u,&v,&c);
                OpC(u,v,c);
            }
        }
    }
    ;
}

HYSBZ 2243的更多相关文章

  1. HDU 3966 & POJ 3237 & HYSBZ 2243 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

  2. HDU 3966 & POJ 3237 & HYSBZ 2243 & HRBUST 2064 树链剖分

    树链剖分是一个很固定的套路 一般用来解决树上两点之间的路径更改与查询 思想是将一棵树分成不想交的几条链 并且由于dfs的顺序性 给每条链上的点或边标的号必定是连着的 那么每两个点之间的路径都可以拆成几 ...

  3. hysbz 2243 染色(树链剖分)

    题目链接:hysbz 2243 染色 题目大意:略. 解题思路:树链剖分+线段树的区间合并,可是区间合并比較简单,节点仅仅要记录左右端点的颜色就可以. #include <cstdio> ...

  4. HYSBZ 2243(树链剖分)

    题目连接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28982#problem/D 题意:给定一棵有n个节点的无根树及点权和m个操作, ...

  5. HYSBZ 2243 染色 (树链拆分)

    主题链接~~> 做题情绪:这题思路好想.调试代码调试了好久.第一次写线段树区间合并. 解题思路: 树链剖分 + 线段树区间合并 线段树的端点记录左右区间的颜色.颜色数目.合并的时候就用区间合并的 ...

  6. HYSBZ 2243(染色)

    题目链接:传送门 题目大意:中文题,略 题目思路:树链剖分,区间更新,区间查询. 闲谈:      只想说这道题做的好苦逼..去长春现场赛之前就没A,回来后又做了2天才A掉,蒟蒻太菜了 这道题也没有想 ...

  7. HYSBZ - 2243 染色 (树链剖分+线段树)

    题意:树上每个结点有自己的颜色,支持两种操作:1.将u到v路径上的点颜色修改为c; 2.求u到v路径上有多少段不同的颜色. 分析:树剖之后用线段树维护区间颜色段数.区间查询区间修改.线段树结点中维护的 ...

  8. HYSBZ - 2243 树链剖分 + 线段树 处理树上颜色段数

    用线段树处理颜色段数 记录区间内的颜色段数,区间右端点的颜色,区间右端点的颜色. int tr[maxn<<2], lc[maxn<<2], rc[maxn<<2] ...

  9. HYSBZ 2038 莫队算法

    小Z的袜子(hose) Time Limit:20000MS     Memory Limit:265216KB     64bit IO Format:%lld & %llu Submit  ...

随机推荐

  1. oracle 存储过程创建及执行简单实例

    1. 创建 CREATE OR REPLACE PROCEDURE getAplage(eNo IN NUMBER,salary OUT NUMBER) AS BEGIN SELECT AplAge ...

  2. Jquery实现账单全部选中和部分选中管理

    在做购物车系统是我们往往会遇到这样一个需求,在点击全选框时我们要将全部的单个账单都选中;在单个选中账单时,如果账单全部被选中则需要全选框处于选中状态,若没有全部被选中则全选框处于没选中状态; 以下是在 ...

  3. 与String有关的强制转换

    String --> int int i = Integer.parseInteger("123"); String --> double double d = Dou ...

  4. selenium移动div里面的滚动条,操作弹出对话框

    还是使用js来移动 首先要定位到这个元素 倾向于使用js来定位元素,输入下面的脚本,按下回车键,即可在调试页面看到对应的div块$("div.table-responsive") ...

  5. [HTML/HTML5]8 使用表格

    8.1  创建基本的表格结构 8.1.1  表格结构 HTML表格包含4种基本元素: table:在HTML中table元素是一个容器,其中包含用于创建表格的其它的元素: tr:表示表格中的行,开始标 ...

  6. C++对于大型图片的加载缩放尝试

    Qt对于图片的操作主要集中在这几个类 QImage ,QImageReader ,QPixmap 其中QImage这个类对图片的缩放有几个很不错的技巧,不过对于大图片却并不好使,当我们去看QImage ...

  7. Maven学习链接

    别人的资料很多且写的很详细,我这里先收藏,等学习到一定阶段且有时间再整理自己的积累. 1.eclipse安装maven插件方法: http://blog.csdn.net/kittyboy0001/a ...

  8. JS学习笔记--仿手机发送内容交互

    学习JS笔记----记录上课中学习的知识点,分享下老师教的内容: 1.html内容 <div id="box"> <div id="message&qu ...

  9. System.Data.Oracleclient需要Oracle客户端软件Version8.1.7或更高版本问题

    C#连接ORACLE报System.Data.Oracleclient需要Oracle客户端软件Version8.1.7或更高版本问题: 开始Webservice在32位系统ORACLE10g库中we ...

  10. sql sever跨数据库复制数据的方法【转】

    1,用Opendatasource系统函数 详细的用法已经注释在sql代码中了.这个是在sqlserver到sqlserver之间的倒数据.2005,2008,2012应该都是适用的. --从远程服务 ...