分析:

区间合并,lcol是左端点的颜色编号,rcol是右端点的颜色编号,那么我们向上合并的时候,如果左儿子的rcol等于右儿子的lcol那么区间的sum--。

另外,如果重链顶的颜色等于重链顶的父节点的颜色,那么ans--;

附上代码:

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <iostream>
using namespace std;
#define N 100005
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
int sum[N<<2],lcol[N<<2],rcol[N<<2],cov[N<<2];
int head[N],cnt,dep[N],anc[N],fa[N],siz[N],son[N];
int idx[N],a[N],p[N],tims,n,Q;
struct node
{int to,next;
}e[N<<1];
void add(int x,int y)
{e[cnt].to=y;e[cnt].next=head[x];head[x]=cnt++;return ;
}
void dfs1(int x,int from)
{fa[x]=from,siz[x]=1,dep[x]=dep[from]+1;for(int i=head[x];i!=-1;i=e[i].next){int to1=e[i].to;if(to1!=from){dfs1(to1,x);siz[x]+=siz[to1];if(siz[son[x]]<siz[to1])son[x]=to1;}}
}
void dfs2(int x,int top)
{idx[x]=++tims;p[tims]=x;anc[x]=top;if(son[x])dfs2(son[x],top);for(int i=head[x];i!=-1;i=e[i].next){int to1=e[i].to;if(to1!=fa[x]&&to1!=son[x]){dfs2(to1,to1);}}
}
void PushUp(int rt)
{lcol[rt]=lcol[rt<<1];rcol[rt]=rcol[rt<<1|1];sum[rt]=sum[rt<<1|1]+sum[rt<<1];if(lcol[rt<<1|1]==rcol[rt<<1])sum[rt]--;return ;
}
void PushDown(int rt)
{if(cov[rt]){cov[rt<<1]=cov[rt<<1|1]=lcol[rt<<1]=rcol[rt<<1]=lcol[rt<<1|1]=rcol[rt<<1|1]=cov[rt];sum[rt<<1]=sum[rt<<1|1]=1;cov[rt]=0;}
}
void build(int l,int r,int rt)
{if(l==r){sum[rt]=1;lcol[rt]=rcol[rt]=a[p[l]];return ;}int m=(l+r)>>1;build(lson);build(rson);PushUp(rt);
}
void Update(int L,int R,int c,int l,int r,int rt)
{if(L<=l&&r<=R){lcol[rt]=rcol[rt]=cov[rt]=c;sum[rt]=1;return ;}PushDown(rt);int m=(l+r)>>1;if(m>=L)Update(L,R,c,lson);if(m<R)Update(L,R,c,rson);PushUp(rt);
}
int query(int L,int R,int l,int r,int rt)
{if(L<=l&&r<=R)return sum[rt];PushDown(rt);int m=(l+r)>>1;int ret=0,vis=0;if(m>=L){vis++;ret+=query(L,R,lson);}if(m<R){vis++;ret+=query(L,R,rson);}if(rcol[rt<<1]==lcol[rt<<1|1]&&vis==2)ret--;return ret;
}
int query_col(int x,int l,int r,int rt)
{if(l==r){return lcol[rt];}PushDown(rt);int m=(l+r)>>1;if(m>=x)return query_col(x,lson);else return query_col(x,rson);
}
int get_lca_query(int x,int y)
{int ret=0;while(anc[x]!=anc[y]){if(dep[anc[x]]<dep[anc[y]])swap(x,y);ret+=query(idx[anc[x]],idx[x],1,n,1);int l=query_col(idx[anc[x]],1,n,1);int r=query_col(idx[fa[anc[x]]],1,n,1);if(l==r)ret--;x=fa[anc[x]];}if(dep[x]>dep[y])swap(x,y);ret+=query(idx[x],idx[y],1,n,1);return ret;
}
void get_lca_Update(int x,int y,int c)
{while(anc[x]!=anc[y]){if(dep[anc[x]]<dep[anc[y]])swap(x,y);Update(idx[anc[x]],idx[x],c,1,n,1);x=fa[anc[x]];}if(dep[x]>dep[y])swap(x,y);Update(idx[x],idx[y],c,1,n,1);return ;
}
char s[20];
int main()
{memset(head,-1,sizeof(head));scanf("%d%d",&n,&Q);for(int i=1;i<=n;i++){scanf("%d",&a[i]);}for(int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);add(x,y);add(y,x);}dfs1(1,0);dfs2(1,1);build(1,n,1);while(Q--){int x,y,z;scanf("%s%d%d",s,&x,&y);if(s[0]=='Q'){printf("%d\n",get_lca_query(x,y));}else{scanf("%d",&z);get_lca_Update(x,y,z);}}return 0;
}

  

转载于:https://www.cnblogs.com/Winniechen/p/9042822.html

[SDOI2011]染色 BZOJ2243 树链剖分+线段树相关推荐

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

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

  2. P2486 [SDOI2011]染色(树链剖分+线段树)

    题干描述 输入描述 输出格式 对于每个询问操作,输出一行答案. 输入输出样例 输入 #1 复制 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. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

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

  4. BZOJ3862Little Devil I——树链剖分+线段树

    题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...

  5. CodeForces - 160D Edges in MST(思维+tarjan/树链剖分+线段树)

    题目链接:点击查看 题目大意:给出一张 n 个点 m 条边组成的带权无向图,现在对于每条边来说,确定一下其分类: 一定是最小生成树上的边 可能是最小生成树上的边 一定不是最小生成树的边 题目分析:两种 ...

  6. CodeForces - 609E Minimum spanning tree for each edge(最小生成树+树链剖分+线段树/树上倍增)

    题目链接:点击查看 题目大意:给出一张 n 个点和 m 条边组成的无向图,现在询问包含每一条边的最小生成树 题目分析:考虑求解次小生成树的思路: 求出最小生成树 ans 枚举每一条非树边 ( u , ...

  7. BZOJ4127Abs——树链剖分+线段树

    题目描述 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 输入 第一行两个整数n和m,表示结点个数和操作数 ...

  8. HDU 2460 Network(双连通+树链剖分+线段树)

    HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链 ...

  9. BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树

    题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...

  10. YbtOJ-染色计划【树链剖分,线段树,tarjan】

    正题 题目大意 给出nnn个点的一棵树,每个点有个颜色aia_iai​,你每次可以选择一个颜色全部变成另一个颜色. 求最少多少次操作可以把一种颜色变成一个完整的连通块. 1≤k≤n≤2×1051\le ...

最新文章

  1. 经常使用的npm命令
  2. Nature Commun. | 假单胞和芽孢杆菌互作共存于寄主的机制,为生物防治提供新思路...
  3. case when用法java_Oracle CASE WHEN 用法介绍
  4. Windows 2003 Server服务器上IIS发布网站具体步骤
  5. altera fpga sdi输出方案_FPGA在电力电子中的应用有哪些?
  6. React Native使用指南-植入原生应用
  7. 能够生成动态图片的R模块:rCharts
  8. 5.1--5.1.2 Permutations of a Multiset 多重集合的排列
  9. 中文语料 自动分词、标注词性 工具
  10. Multi-Scale Boosted Dehazing Network with Dense Feature Fusion笔记和代码
  11. linux vim 安装失败,ubuntu安装vim失败怎么办
  12. 【模电】0007 有源滤波器2(二阶有源滤低通波器)
  13. eclipse 工具翻译插件安装
  14. 关于粒子群算法的两种惯性权重
  15. echarts地图闪烁点大小设置
  16. 项目管理知识体系指南(五)项目时间管理
  17. netlink_unicast return -11 (EAGAIN)
  18. 苹果ppt_熬夜看完苹果发布会,我居然学会了用PPT做霓虹灯特效?!
  19. 晶体三极管原理及应用
  20. jmeter前后置处理器

热门文章

  1. 作业帮基于 Flink 的实时计算平台实践
  2. FFmpeg实现多段小视频合成
  3. 插件开发之360 DroidPlugin源码分析(三)Binder代理
  4. 早期微信抢红包插件项目分享
  5. python数据库操作——连接Oracle
  6. linq判断集合中相同元素个数_高中数学:集合与函数概念知识点汇总
  7. python中哈希是什么意思_python 中倒是什么事可哈希的意思那?
  8. 被替换的项目不是替换值长度的倍数_机器学习中处理缺失值的9种方法
  9. linux编译生成GUI程序命令,linux – 快速开发GUI命令行
  10. android接口类命名规范_Android开发规范