题目大意:

  给定一棵有n个节点的无根树和m个操作,操作有2类:

  1、将节点a到节点b路径上所有点都染成颜色c;

  2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段)

思路:

  树剖之后,维护其两端的颜色、答案和标记即可。

代码:

#include<cstdio>
#include<iostream>
#define N 100001
using namespace std;
int n,m,cnt,dfn,vis[N],head[N],to[N<<],next[N<<],deep[N],size[N],top[N],id[N],v[N],pa[N],lazy[N<<],lc[N<<],rc[N<<],sum[N<<]; void ins(int x,int y)
{
to[++cnt]=y,next[cnt]=head[x],head[x]=cnt;
} void dfs1(int x)
{
size[x]=vis[x]=;
for (int i=head[x];i;i=next[i])
if (!vis[to[i]])
{
deep[to[i]]=deep[x]+;
pa[to[i]]=x;
dfs1(to[i]);
size[x]+=size[to[i]];
}
} void dfs2(int x,int chain)
{
int k=,i;
id[x]=++dfn;
top[x]=chain;
for (i=head[x];i;i=next[i])
if (deep[to[i]]>deep[x] && size[to[i]]>size[k]) k=to[i];
if (!k) return;
dfs2(k,chain);
for (i=head[x];i;i=next[i])
if (deep[to[i]]>deep[x] && to[i]!=k) dfs2(to[i],to[i]);
} void build(int l,int r,int cur)
{
sum[cur]=,lazy[cur]=-;
if(l==r)return;
int mid=l+r>>;
build(l,mid,cur<<),build(mid+,r,cur<<|);
} void update(int k)
{
lc[k]=lc[k<<],rc[k]=rc[k<<|];
if (rc[k<<]^lc[k<<|]) sum[k]=sum[k<<]+sum[k<<|];
else sum[k]=sum[k<<]+sum[k<<|]-;
} void pushdown(int l,int r,int k)
{
int tmp=lazy[k]; lazy[k]=-;
if (tmp==- || l==r) return;
sum[k<<]=sum[k<<|]=;
lazy[k<<]=lazy[k<<|]=tmp;
lc[k<<]=rc[k<<]=tmp;
lc[k<<|]=rc[k<<|]=tmp;
} void change(int L,int R,int l,int r,int cur,int val)
{
if (l==L && r==R) { lc[cur]=rc[cur]=val; sum[cur]=; lazy[cur]=val; return; }
int mid=L+R>>; pushdown(L,R,cur);
if (r<=mid) change(L,mid,l,r,cur<<,val);
else if (l>mid) change(mid+,R,l,r,cur<<|,val);
else change(L,mid,l,mid,cur<<,val),change(mid+,R,mid+,r,cur<<|,val);
update(cur);
} int ask(int L,int R,int l,int r,int cur)
{
if (l==L && r==R) return sum[cur];
int mid=L+R>>; pushdown(L,R,cur);
if (r<=mid) return ask(L,mid,l,r,cur<<);
else if (l>mid) return ask(mid+,R,l,r,cur<<|);
else
{
int tmp=;
if (rc[cur<<]^lc[cur<<|]) tmp=;
return ask(L,mid,l,mid,cur<<)+ask(mid+,R,mid+,r,cur<<|)-tmp;
}
} int getc(int l,int r,int cur,int x)
{
if (l==r) return lc[cur];
int mid=l+r>>; pushdown(l,r,cur);
if (x<=mid) return getc(l,mid,cur<<,x);
else return getc(mid+,r,cur<<|,x);
} int solvesum(int x,int y)
{
int sum=;
for (;top[x]!=top[y];x=pa[top[x]])
{
if (deep[top[x]]<deep[top[y]]) swap(x,y);
sum+=ask(,n,id[top[x]],id[x],);
if (getc(,n,,id[top[x]])==getc(,n,,id[pa[top[x]]])) sum--;
}
if (deep[x]>deep[y]) swap(x,y);
return sum+=ask(,n,id[x],id[y],);
} void solvechange(int x,int y,int val)
{
for (;top[x]!=top[y];x=pa[top[x]])
{
if (deep[top[x]]<deep[top[y]]) swap(x,y);
change(,n,id[top[x]],id[x],,val);
}
if (deep[x]>deep[y]) swap(x,y);
change(,n,id[x],id[y],,val);
} int main()
{
int i,a,b,c;
scanf("%d%d",&n,&m);
for(i=;i<=n;i++)scanf("%d",&v[i]);
for(i=;i<n;i++) scanf("%d%d",&a,&b),ins(a,b),ins(b,a);
dfs1(),dfs2(,),build(,n,);
for(i=;i<=n;i++) change(,n,id[i],id[i],,v[i]);
for(i=;i<=m;i++)
{
char ch[];
scanf("%s",ch);
if(ch[]=='Q')
{
scanf("%d%d",&a,&b);
printf("%d\n",solvesum(a,b));
}
else
{
scanf("%d%d%d",&a,&b,&c);
solvechange(a,b,c);
}
}
return ;
}

[SDOI2011]染色 题解的更多相关文章

  1. BZOJ2243:[SDOI2011]染色——题解

    http://www.lydsy.com/JudgeOnline/problem.php?id=2243 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点 ...

  2. 洛谷P2486 [SDOI2011]染色 题解 树链剖分+线段树

    题目链接:https://www.luogu.org/problem/P2486 首先这是一道树链剖分+线段树的题. 线段树部分和 codedecision P1112 区间连续段 一模一样,所以我们 ...

  3. 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树

    [BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...

  4. Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 5020  Solved: 1872[Submit][Status ...

  5. 2243: [SDOI2011]染色

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 3113  Solved: 1204[Submit][Status ...

  6. bzoj 2243 [SDOI2011]染色(树链剖分+线段树合并)

    [bzoj2243][SDOI2011]染色 2017年10月20日 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询 ...

  7. [Luogu 2486] SDOI2011 染色

    [Luogu 2486] SDOI2011 染色 树剖水题,线段树维护. 详细题解不写了. 我只想说我写的线段树又变漂亮了qwq #include <algorithm> #include ...

  8. BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  9. BZOJ 2243: [SDOI2011]染色 树链剖分+线段树区间合并

    2243: [SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数 ...

随机推荐

  1. Java -- 子类使用super调用父类的方法A,A 调用了方法B,子类也override方法B,那么super.A()最终调用到了子类的B方法

    public class SuperClass{ public void printA(){ System.out.print("SuperClass-printA"); prin ...

  2. 《CLR via C#》读书笔记(6)类型和成员基础

    6.1 类型的各种成员 在一个类型中,可以定义0个或者多个以下种类的成员: 常量 常量是在编译时设置其值并且永远不能更改其值的字段.使用常量可以为特殊值提供有意义的名称以代替数字文本,以使代码变得更容 ...

  3. Easy UI 面板

    驾考园 http://www.jiakaoyuan.com 驾考园信息网 下载(源码)

  4. Linux 标准目录结构

    初学Linux,首先需要弄清Linux 标准目录结构 / root --- 启动Linux时使用的一些核心文件.如操作系统内核.引导程序Grub等. home --- 存储普通用户的个人文件 ftp ...

  5. 谈谈Delphi中的类和对象1---介绍几个概念 && 对象是一个地地道道的指针

    参考:http://blog.163.com/liang_liu99/blog/static/88415216200952123412180/ 以下的介绍主要针对的是Delphi的面向对象的知识,可能 ...

  6. 使用html5 canvas绘制图片

    注意:本文属于<html5 Canvas绘制图形入门详解>系列文章中的一部分.如果你是html5初学者,仅仅阅读本文,可能无法较深入的理解canvas,甚至无法顺畅地通读本文.请点击上述链 ...

  7. Powershell查看SSAS Cube占用磁盘空间

    以下是用powershell查看Cube占用磁盘空间大小的方式.可以编译成函数也可以直接把参数改成需要的服务器名称. Param($ServerName="SERVERNAME") ...

  8. PHP不同域名cookie共享(单点登录实现原理)

    PHP使用P3P完成COOKIE跨域操作实际实用中,类似的需求有,比如说我们有两个域名,我们想实现在一个域名登录后,能自动完成另一个域名的登录,也就是单点登录(SSO)功能.为了测试的方便,先编辑ho ...

  9. php的时间输出格式

    php中时间一般分为两种格式,一种是标准时间格式timestamp,即Y-m-d G:i:s.另一种就是时间戳. 例如: 一.标准时间与时间戳转换: //获得服务端系统时间 date_default_ ...

  10. C语言中的位操作(14)--反转比特位

    本篇文章主要讲述几种反转比特位的方法: 将一个32位数:abcd efgh 转置为hgfe dcba 1.常规方法 unsigned int v; // 目标待转置数 unsigned int r = ...