原题链接


肯定是树链剖分的题啦

树剖怎么做可以看我上一篇博客

如果我们已经剖完了:

然后考虑怎么维护重链和查询

用线段树维护的时候当前区间的区间颜色个数应该等于左儿子+右儿子,但是当左儿子的右端点和右儿子的左端点颜色一样,显然区间数要减1

所以每个节点存一下左端点的右端点颜色正常维护即可

考虑查询,在同一重链上的点显然线段树可以解决,当top[u]!=top[v]的时候,得让deep较深的爬树,那么答案就要+=爬树那一段的区间个数

但是有可能的是fa[top[u]]的颜色和top[u]的颜色相等,这个时候需要答案--,这样才能保证下次爬树的时候不会多算

注意:请写单点查询询问颜色,因为fa[top[u]]和top[u]是轻链的两端,不能保证在线段树中编号连续,所以不能区间查询是否是个数是1

修改同理,爬树的时候修改即可

 #include<cstdio>
#include<algorithm>
#include<cstring>
#define N 100010
using namespace std;
int n,m,head[N],indx[N],pos[N],fa[N],ecnt,color[N],deep[N],sz[N],top[N],a,b,c,tot,son[N];
char s[N];
int read()
{
int ret=,neg=;
char j=getchar();
for (;j>'' || j<'';j=getchar())
if (j == '-') neg=-;
for (;j>='' && j<='';j=getchar())
ret=ret*+j-'';
return ret*neg;
}
struct adj
{
int nxt,v;
}e[*N];
struct node
{
int l,r,Lcolor,Rcolor,sum,lz;
}t[*N];
void add(int u,int v)//加边
{
e[++ecnt].v=v;
e[ecnt].nxt=head[u];
head[u]=ecnt;
e[++ecnt].v=u;
e[ecnt].nxt=head[v];
head[v]=ecnt;
}
void dfs1(int x,int father,int d)//第一次dfs
{
fa[x]=father,deep[x]=d,sz[x]=;
for (int i=head[x];i;i=e[i].nxt)
{
int v=e[i].v;
if (v==father) continue;
dfs1(v,x,d+);
sz[x]+=sz[v];
if (sz[son[x]]<sz[v]) son[x]=v;
}
}
void dfs2(int x,int TOP)//第二次dfs
{
pos[x]=++tot;
indx[tot]=x;
top[x]=TOP;
if (son[x]) dfs2(son[x],TOP);
for (int i=head[x];i;i=e[i].nxt)
{
int v=e[i].v;
if (v==fa[x] || v==son[x]) continue;
if (v!=) dfs2(v,v);
}
}
void pushup(int p)//线段树更新
{
t[p].sum=t[p<<].sum+t[p<<|].sum;
if (t[p<<].Rcolor==t[p<<|].Lcolor) t[p].sum--;
t[p].Lcolor=t[p<<].Lcolor;
t[p].Rcolor=t[p<<|].Rcolor;
}
void pushdown(int p)//lazy下放
{
if (t[p].l==t[p].r || t[p].lz==-) return;
int w=t[p].lz;
t[p<<].Lcolor=t[p<<].Rcolor=t[p<<|].Lcolor=t[p<<|].Rcolor=t[p<<].lz=t[p<<|].lz=w;
t[p<<].sum=t[p<<|].sum=;
t[p].lz=-;
}
void build(int p,int l,int r)//建树
{
t[p].l=l,t[p].r=r,t[p].lz=-;
if (l==r)
{
t[p].Lcolor=t[p].Rcolor=color[indx[l]];
t[p].sum=;
}
else
{
int mid=l+r>>;
build(p<<,l,mid);
build(p<<|,mid+,r);
pushup(p);
}
}
void modify(int p,int l,int r,int k)//区间修改
{
if (l==t[p].l && r==t[p].r)
{
t[p].sum=;
t[p].Lcolor=t[p].Rcolor=k;
t[p].lz=k;
return;
}
pushdown(p);
int mid=t[p].l+t[p].r>>;
if (r<=mid)
modify(p<<,l,r,k);
else if (l>mid) modify(p<<|,l,r,k);
else
modify(p<<,l,mid,k),modify(p<<|,mid+,r,k);
pushup(p);
}
int query(int p,int l,int r)//区间询问
{
if (l==t[p].l && r==t[p].r)
return t[p].sum;
pushdown(p);
int mid=t[p].l+t[p].r>>;
if (r<=mid)
return query(p<<,l,r);
if (l>mid) return query(p<<|,l,r);
int tmp=query(p<<,l,mid)+query(p<<|,mid+,r);
if (t[p<<].Rcolor==t[p<<|].Lcolor) tmp--;
return tmp;
}
int Qcolor(int p,int l)//单点询问
{
if (t[p].l==t[p].r && t[p].l==l) return t[p].Lcolor;
pushdown(p);
int mid=t[p].l+t[p].r>>;
if (l<=mid) return Qcolor(p<<,l);
else return Qcolor(p<<|,l);
}
void getcolor(int a,int b,int w)//修改
{
while (top[a]!=top[b])//爬树
{
if (deep[top[a]]<deep[top[b]]) swap(a,b);
modify(,pos[top[a]],pos[a],w);
a=fa[top[a]];
}
if (deep[a]>deep[b]) swap(a,b);
modify(,pos[a],pos[b],w);
}
int querycolor(int u,int v)//询问
{
int ret=;
while (top[u]!=top[v])
{
if (deep[top[u]]<deep[top[v]]) swap(u,v);
ret+=query(,pos[top[u]],pos[u]);
if (Qcolor(,pos[fa[top[u]]])==Qcolor(,pos[top[u]])) ret--;//看题解
u=fa[top[u]];
}
if (deep[u]>deep[v]) swap(u,v);
return ret+query(,pos[u],pos[v]);
}
int main()
{
n=read(),m=read();
for (int i=;i<=n;i++)
color[i]=read();
for (int i=;i<n;i++)
add(read(),read());
dfs1(,,);
dfs2(,);
build(,,n);
while (m--)
{
scanf("%s",s);
if (s[]=='C')
{
a=read(),b=read(),c=read();
getcolor(a,b,c);
}
else
{
scanf("%d%d",&a,&b);
printf("%d\n",querycolor(a,b));
}
}
return ;
}

POJ 2243 [SDOI2011]染色 | 树链剖分+线段树的更多相关文章

  1. 2243: [SDOI2011]染色 树链剖分+线段树染色

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

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

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

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

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

  4. B20J_2243_[SDOI2011]染色_树链剖分+线段树

    B20J_2243_[SDOI2011]染色_树链剖分+线段树 一下午净调这题了,争取晚上多做几道. 题意: 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成 ...

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

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

  6. POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )

    POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...

  7. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  8. 【bzoj1959】[Ahoi2005]LANE 航线规划 树链剖分+线段树

    题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...

  9. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  10. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

随机推荐

  1. swiper轮播始终居中active图片

    用的是vue-awesome-swiper 在vue项目中,参数方法与swiper一致.使用场景如下: 左侧小图一共八张,默认显示的是三张,始终保持activeimg在中间,提升用户体验度.swipe ...

  2. LeetCode105. Construct Binary Tree from Preorder and Inorder Traversal

    题目 根据一棵树的前序遍历与中序遍历构造二叉树. 注意: 你可以假设树中没有重复的元素. 例如,给出 前序遍历 preorder = [3,9,20,15,7] 中序遍历 inorder = [9,3 ...

  3. [vijos p1028] 魔族密码

    描述 风之子刚走进他的考场,就……花花:当当当当~~偶是魅力女皇——花花!!^^(华丽出场,礼炮,鲜花)风之子:我呕……(杀死人的眼神)快说题目!否则……-_-###花花:……咦~~好冷~~我们现在要 ...

  4. CMD批处理复制目录下所有文件

    从我接触编程时,WIN7已经是最普及的系统了. 有一天,我需要在服务器更新某个软件或游戏的时候,我都需要先在其中一台服务器下载更新, 然后同步到其他服务器,而且这种操作也是非常频繁的,我就想写个批处理 ...

  5. Hutool Wiki For java

    发现一款不错的java工具类, http://www.hutool.cn/ Hutool的使用文档. 项目见 https://github.com/looly/hutool 以及 http://git ...

  6. js点击获取标签里面id属性

    <html xmlns="http://www.w3.org/1999/xhtml"> <head > <title></title> ...

  7. 微信小程序开发入门学习(2):小程序的布局

    概述 小程序的布局采用了和Css3中相同的 flex(弹性布局)方式,使用方法也类似(只是属性名不同而已). 水平排列 默认是从左向右水平依次放置组件,从上到下依次放置组件. 任何可视组件都需要使用样 ...

  8. javascript中string对象方法中的slice、substring、substr的区别联系

    1.slice.substring.snustr均属于String的对象方法,用于截取或提取字符串片段,三者均布破坏原先的字符串,而是以新的字符串返回被提取的部分. <script> va ...

  9. 【转载】C++中的static关键字的总结

    本文前半部分转自:博主chao_yu 本文后半部分转自:博主VincentCZW 静态变量作用范围在一个文件内,程序开始时分配空间,结束时释放空间,默认初始化为0,使用时可以改变其值. 静态变量或静态 ...

  10. 深入理解yii2之RBAC(模块化系统)

    一.前言 上一篇文章我们已经大致谈过RBAC到底是什么和yii2底层RBAC接口的分析. 下面我深入理解一下RBAC权限分配,深入理解下yii2底层RBAC扩展,以及它是如何针对模块化系统的开发的? ...