树链剖分模板题。线段树维护每个段中的颜色数、左端点颜色、右端点颜色。

pushup: col[rt]=col[rt<<1]+col[rt<<1|1]-(Rcol[rt<<1]==Lcol[rt<<1|1]);

在合并各个链的答案时,要注意若两头颜色相同,ans--。
【教训:树链剖分题在进行建立线段树树时,要注意下面代码中的标注部分。否则会WA】
Code:
 #include<cstdio>
#include<algorithm>
using namespace std;
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define maxn 100001
int col[maxn<<],L[maxn<<],R[maxn<<],delta[maxn<<],n,m,Val[maxn],Num[maxn];
int V[maxn<<],First[maxn<<],Next[maxn<<],All_Lcol,All_Rcol,en;
bool vis[maxn];
int top[maxn],son[maxn],tot,dep[maxn],fa[maxn],siz[maxn],Map[maxn];
inline void AddEdge(const int &UU,const int &VV){V[++en]=VV;Next[en]=First[UU];First[UU]=en;}
inline void pushup(const int &rt)
{
L[rt]=L[rt<<];
R[rt]=R[rt<<|];
col[rt]=col[rt<<]+col[rt<<|]-(R[rt<<]==L[rt<<|]);
}
inline void pushdown(const int &rt)
{
if(delta[rt]!=-)
{
L[rt<<]=R[rt<<]=L[rt<<|]=R[rt<<|]=delta[rt];
delta[rt<<]=delta[rt<<|]=delta[rt];
delta[rt]=-;
col[rt<<]=col[rt<<|]=;
}
}
void buildtree(int rt,int l,int r)
{
delta[rt]=-;
if(l==r)
{
col[rt]=;
L[rt]=R[rt]=Val[Map[l]];//l是线段树中的新位置,
//Map[l]表示新位置对应的在树中的编号是谁
return;
}
int m=l+r>>;
buildtree(lson);
buildtree(rson);
pushup(rt);
}
void update(int ql,int qr,int v,int rt,int l,int r)
{
if(ql<=l&&r<=qr)
{
delta[rt]=L[rt]=R[rt]=v;//更新当前结点的标记值
col[rt]=;
return;
}
pushdown(rt);//将该节点的标记下传到孩子们
int m=l+r>>;
if(ql<=m)
update(ql,qr,v,lson);
if(m<qr)
update(ql,qr,v,rson);
pushup(rt);
}
int query(int ql,int qr,int rt,int l,int r)
{
if(ql==l)
All_Lcol=L[rt];
if(r==qr)
All_Rcol=R[rt];
if(ql<=l&&r<=qr)
return col[rt];
pushdown(rt);//将该节点的标记下传到孩子们
int m=l+r>>,res=,now1=-,now2=-;
if(ql<=m)
{
res+=query(ql,qr,lson);
now1=R[rt<<];
}
if(m<qr)
{
res+=query(ql,qr,rson);
now2=L[rt<<|];
}
res-=(now1==now2 && now1!=-);
return res;
}
inline void Update(int u,int v,int val)
{
int f1=top[u],f2=top[v];
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(u,v);
swap(f1,f2);
}
update(Num[f1],Num[u],val,,,n);
u=fa[f1];
f1=top[u];
}
if(dep[u]<dep[v])
swap(u,v);
update(Num[v],Num[u],val,,,n);
}
inline int Query(int u,int v)
{
int f1=top[u],f2=top[v],ans=,t1=-,t2=-;
while(f1!=f2)
{
if(dep[f1]<dep[f2])
{
swap(u,v);
swap(f1,f2);
swap(t1,t2);
}
ans+=query(Num[f1],Num[u],,,n);
ans-=(t1==All_Rcol);
t1=All_Lcol;
u=fa[f1];
f1=top[u];
}
if(dep[u]<dep[v])
{
swap(u,v);
swap(t1,t2);
}
ans+=query(Num[v],Num[u],,,n);
ans-=((t1==All_Rcol&&t1!=-)+(t2==All_Lcol&&t2!=-));
return ans;
}
void dfs1(int cur,int father,int depth)
{
fa[cur]=father;
dep[cur]=depth;
siz[cur]=;
for(int i=First[cur];i;i=Next[i])
if(!vis[V[i]])
{
vis[V[i]]=true;
dfs1(V[i],cur,depth+);
siz[cur]+=siz[V[i]];
if(siz[V[i]]>siz[son[cur]])
son[cur]=V[i];
vis[V[i]]=false;
}
}
void dfs2(int cur)
{
if(son[cur]&&!vis[son[cur]])
{
vis[son[cur]]=true;
top[son[cur]]=top[cur];
Num[son[cur]]=++tot;
Map[tot]=son[cur];
dfs2(son[cur]);
vis[son[cur]]=false;
}
for(int i=First[cur];i;i=Next[i])
if(son[cur]!=V[i]&&!vis[V[i]])
{
vis[V[i]]=true;
top[V[i]]=V[i];
Num[V[i]]=++tot;
Map[tot]=V[i];
dfs2(V[i]);
vis[V[i]]=false;
}
}
int Res,num;
char C;
char CH[];
inline int getint()
{
Res=;
C='*';
while(C<''||C>'')
C=getchar();
while(C>=''&&C<='')
{
Res=Res*+(C-'');
C=getchar();
}
return Res;
}
inline void putint(int x)
{
num=;
while(x>)
CH[++num]=x%,x/=;
while(num)
putchar(CH[num--]+);
putchar('\n');
}
int main()
{
int x,y,a,b,c;
char op;
n=getint();
m=getint();
for(int i=;i<=n;i++)
Val[i]=getint();
for(int i=;i<n;i++){x=getint();y=getint();AddEdge(x,y);AddEdge(y,x);}
top[]=;
Num[]=++tot;
Map[tot]=;
vis[]=true;
dfs1(,,);
dfs2();
buildtree(,,n);
for(int i=;i<=m;i++)
{
getchar();
op=getchar();
a=getint();
b=getint();
if(op=='C')
{
c=getint();
Update(a,b,c);
}
else
putint(Query(a,b));
}
return ;
}

【树链剖分】bzoj2243 [SDOI2011]染色的更多相关文章

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

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

  2. bzoj-2243 2243: [SDOI2011]染色(树链剖分)

    题目链接: 2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6267  Solved: 2291 Descript ...

  3. bzoj2243[SDOI2011]染色 树链剖分+线段树

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

  4. BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ...

  5. BZOJ2243 SDOI2011 染色 【树链剖分】

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

  6. [BZOJ2243][SDOI2011]染色 解题报告|树链剖分

    Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...

  7. BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)

    题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...

  8. BZOJ2243: [SDOI2011]染色(树链剖分/LCT)

    Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如 ...

  9. 【BZOJ2243】【SDOI2011】染色(树链剖分,线段树)

    题面 我们也要换个花样,这回提供洛谷的题面 题解 线段树+树链剖分大水题 维护颜色段的方法很简单呀... 维护当前区间内的颜色段个数, 以及当前区间左端和右端的颜色, 合并的时候考虑是否要减一下就行了 ...

随机推荐

  1. nodewebkitV0.21.6版本的学习

    1.下载 https://nwjs.io/ 建议下载sdk版本,有调试功能,正式发布时,使用normal版本 下载以后解压,得到的文件目录如下 点击nw.exe,显示如下 2.hello world ...

  2. linux 服务简介

    Linux服务(Linux services)对于每个应用Linux的用户来说都很重要.关闭不需要的服务,可以让Linux运行的更高效,但并不是所有的Linux服务都可以关闭.今天安装了一次CentO ...

  3. 2017-2018-1 20179205《Linux内核原理与设计》第三周作业

    <Linux内核原理与分析>第三周作业 教材学习总结 第三章 进程管理 进程是Unix操作系统抽象概念中最基本的一种,是正在执行的程序代码的实时结果:线程,是在进程中活动的对象.而Linu ...

  4. Centos7的iso everything与DVD以及Live的区别

    DVD.ISO 可以用安装程序安装的所有安装包,推荐镜像 Netinstall.iso 从网络安装或者救援系统 Everything.iso 包含centos7的一套完整的软件包,可以用来安装系统或者 ...

  5. ubuntu下virtualbox安装freebsd及初步配置

    最近尝试了在虚拟机中安装freebsd并进行尝试性的使用 获取镜像 在freebsd的官网,https://www.freebsd.org,即可看到 "Download Freebsd&qu ...

  6. python基础=== itertools介绍(转载)

    原文链接:http://python.jobbole.com/85321/ Python提供了一个非常棒的模块用于创建自定义的迭代器,这个模块就是 itertools.itertools 提供的工具相 ...

  7. codevs 1038 一元三次方程求解 NOIP2001提高组

    题目链接:http://codevs.cn/problem/1038/ 题解: 嗯,exm?才知道二分隶属搜索专题…… 对-100到100枚举,按照题目中的提示,当当fi*fi+1<0时,二分深 ...

  8. Win10下Anaconda3安装CPU版本TensorFlow并使用Pycharm开发

    环境:windows10 软件:Anaconda3 1.安装Anaconda 选择相应的Anaconda进行安装,下载地址点击这里,下载对应系统版本的Anaconda3. 运行 开始菜单->An ...

  9. Matcher匹配器查找字符串指定内容

    public static void main(String[] args) { String s = "我的手机号码是18988888888,曾经用过18987654321,还用过1881 ...

  10. poj 1742(好题,楼天城男人八题,混合背包)

    Coins Time Limit: 3000MS   Memory Limit: 30000K Total Submissions: 33269   Accepted: 11295 Descripti ...