【题目链接】

【思路】:

涉及到树上区间修改操作,所以使用树链剖分,涉及到区间查询,所以使用线段树。

update操作时,就正常操作,难点在于query操作的计数。

因为树链剖分的dfs序只能保证一条重链上的dfn[]连续,不能使得任意两点之间简单路径上的dfn[]连续,所以当x往上跳到fa[top[x]]时,要判断

top[x]的颜色与fa[top[x]]的颜色是否相同,如果相同要再减一。

以及在线段树中query操作和pushUp时,都要判断左儿子的右端点与右儿子的左端点是否相同,如果在pushUp中相同,则令此时的segtree[id]减一,

如果在query中相同,那么使得query函数返回的结果减一。 接下来上代码。

#include <bits/stdc++.h>
using namespace std; const int maxn = 1e5 + ;
int n, m, a[maxn];
int segtree[maxn<<], lazy[maxn<<], lft[maxn<<], rht[maxn<<];
int head[maxn], tot, cnt;
int fa[maxn], top[maxn], dfn[maxn], rk[maxn], siz[maxn], dep[maxn], son[maxn];
struct edge{
int to,next;
} ed[maxn<<];
inline int read(){
int k=, f=;
char ch=getchar();
while( ch>'' || ch<'' ){ if(ch=='-') f=-; ch=getchar(); }
while( ch>='' && ch<='' ){ k=k*+ch-''; ch=getchar(); }
return k*f;
} inline void init(){
memset( head ,-, sizeof(head) );
memset( lazy, -, sizeof(lazy) );
tot = ;
} inline void add( int u, int v ){
ed[++tot].to = v; ed[tot].next = head[u]; head[u] = tot;
ed[++tot].to = u; ed[tot].next = head[v]; head[v] = tot;
} inline void dfs1( int x ){
siz[x] = ;
for( int i=head[x]; ~i; i=ed[i].next ){
int y = ed[i].to;
if( y==fa[x] ) continue;
dep[y] = dep[x]+;
fa[y] = x;
dfs1(y);
siz[x] += siz[y];
if( son[x]== || siz[y]>siz[son[x]] ) son[x] = y;
}
} inline void dfs2( int x, int tp ){
top[x] = tp;
dfn[x] = ++cnt;
rk[cnt] = x;
if( son[x] ) dfs2( son[x], tp );
for( int i=head[x]; ~i; i=ed[i].next ){
int y = ed[i].to;
if( y!=fa[x] && y!=son[x] ) dfs2(y, y);
}
} inline void pushUp( int id ){
segtree[id] = segtree[id<<] + segtree[id<<|];
if( lft[id<<|]==rht[id<<] ) segtree[id] --;
lft[id] = lft[id<<]; rht[id] = rht[id<<|];
} inline void pushDown( int id ){
if( lazy[id]==- ) return;
lazy[id<<] = lazy[id<<|] = lazy[id];
segtree[id<<] = segtree[id<<|] = ;
lft[id<<] = lft[id<<|] = rht[id<<] = rht[id<<|] = lazy[id];
lazy[id] = -;
} inline void build( int l, int r, int id ){
if( l==r ){
lft[id] = rht[id] = a[rk[l]];
segtree[id] = ;
return ;
}
int mid=l+r>>;
build( l, mid, id<< );
build( mid+, r, id<<| );
pushUp(id);
} inline void update_tree( int l, int r, int ql, int qr, int id, int c ){
if( ql<=l && qr>=r ){
segtree[id] = ;
lft[id] = rht[id] = c;
lazy[id] = c;
return ;
}
pushDown(id);
int mid = l+r>>;
if( ql<=mid ) update_tree( l, mid, ql, qr, id<<, c );
if( qr>mid ) update_tree( mid+, r, ql, qr, id<<|, c );
pushUp(id);
} inline int query( int l, int r, int ql, int qr, int id ){
if( ql<=l && qr>=r ) return segtree[id];
pushDown(id);
int mid = l+r>>;
int res = ;
if( ql<=mid ) res += query( l, mid, ql, qr, id<< );
if( qr>mid ) res += query( mid+, r, ql, qr, id<<| );
if( ql<=mid && qr>mid && lft[id<<|]==rht[id<<] ) res--; //这里也要判断一次是否相同,前提是要跨立区间
return res;
} inline int color_query( int l, int r, int idx, int id ){
if( l==r ) return lft[id];
pushDown(id);
int mid = l+r>>;
if( idx<=mid ) return color_query( l, mid, idx, id<< );
else return color_query( mid+, r, idx, id<<| );
} inline void swap( int &x, int &y ){ x^=y^=x^=y; } inline int sum( int x, int y ){
int res = ;
while( top[x]!=top[y] ){
if( dep[top[x]]<dep[top[y]] ) swap(x, y);
res += query(, n, dfn[top[x]], dfn[x], );
if( color_query(, n, dfn[top[x]], )==color_query(, n, dfn[fa[top[x]]], ) ) res --; //颜色相同减一
x = fa[top[x]];
}
if( dfn[x]>dfn[y] ) swap(x, y);
res += query( , n, dfn[x], dfn[y], );
return res== ? :res;
} inline void update_chain( int x, int y, int c ){
while( top[x]!=top[y] ){
if( dep[top[x]]<dep[top[y]] ) swap(x, y);
update_tree(, n, dfn[top[x]], dfn[x], , c );
x = fa[top[x]];
}
if( dfn[x]>dfn[y] ) swap(x, y);
update_tree( , n, dfn[x], dfn[y], , c );
} int main(){
// freopen("in.txt", "r", stdin);
init();
n = read(); m = read();
for( int i=; i<=n; i++ ) a[i] = read();
for( int i=; i<n; i++ ){
int u=read(), v=read();
add(u, v);
}
dep[] = fa[] = ;
dfs1();
dfs2(, );
build( , n, );
char ch[];
while( m-- ){
int x, y, z;
scanf("%s", ch);
x = read(); y = read();
if( ch[]=='Q' ) printf("%d\n", sum(x, y));
else{
z = read();
update_chain(x, y, z);
}
} return ;
}

洛谷P2486 [SDOI2011]染色(树链剖分+线段树判断边界)的更多相关文章

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

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

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

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

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

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

  4. 洛谷P4092 [HEOI2016/TJOI2016]树 并查集/树链剖分+线段树

    正解:并查集/树链剖分+线段树 解题报告: 传送门 感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ 首先说下并查集的方法趴QwQ 首先离线,读入所有操作,然后dfs遍历 ...

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

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

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

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

  7. 洛谷P3313 [SDOI2014]旅行 题解 树链剖分+线段树动态开点

    题目链接:https://www.luogu.org/problem/P3313 这道题目就是树链剖分+线段树动态开点. 然后做这道题目之前我们先来看一道不考虑树链剖分之后完全相同的线段树动态开点的题 ...

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

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

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

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

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

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

随机推荐

  1. Linux配置DHCP服务器,DHCP中继配置

    配置dhcp服务器 第一步:配置网卡 第二步: 安装dhcp (需要先构建yum仓库,构建yum仓库的方法在之前的博客里有) 编写dhcp.conf文件 进去以后会出现这个内容 需要执行下面的内容将内 ...

  2. 洛谷 P4053 [JSOI2007]建筑抢修

    传送门 思路 首先题意比较容易明白: n个建筑需要修复,只能同时修一个建筑,每个建筑修复需要t1时间,且必须在t2时间前修完,否则此建筑报废 问最多能修好多少个建筑 如果一个建筑在规定时间内没有修好的 ...

  3. API加密框架原理解密

    关于框架的使用文章请参考: 前后端API交互如何保证数据安全性?:http://cxytiandi.com/blog/detail/20235 API数据加密框架monkey-api-encrypt: ...

  4. java web开发入门六(spring mvc)基于intellig idea

    spring mvc ssm=spring mvc+spring +mybatis spring mvc工作流程 1A)客户端发出http请求,只要请求形式符合web.xml文件中配置的*.actio ...

  5. 动图+源码,演示 Java 中常用数据结构执行过程及原理

    ​阅读本文大概需要 3.7 分钟. 作者:大道方圆 cnblogs.com/xdecode/p/9321848.html 最近在整理数据结构方面的知识, 系统化看了下Java中常用数据结构, 突发奇想 ...

  6. 基于Redis实现分布式定时任务调度

    项目开发过程中,难免会有许多定时任务的需求进来.如果项目中还没有引入quarzt框架的情况下,我们通常会使用Spring的@Schedule(cron="* * * * *")注解 ...

  7. iphone 移动端操作记录

    iPhone和Safari浏览器的后退按钮操作,是直接载入缓存中的页面,不会加载js文件,不会执行ready,onload函数,但是加载html页面会跑pageshow事件,因此有回退动作需要重新加载 ...

  8. Extra:Cg Math Functions

    常用Cg函数 数学函数 abs(x):绝对值 // float类型的实现 float abs(float x) { return max(-a, a); } sin(x):正弦,输入为弧度 // fl ...

  9. WindowsServer --------- 在服务器中安装sqlserver 数据库

    数据库文件可能比较大可以通过盘符映射来进行传递,就是时间比较慢 方法,上一片就是介绍如何进行传递    点击这个连接 安装sqlserver 2014 数据库 要是没有密钥可以试试这个 一般  .Ne ...

  10. VUE方法

    1.$event 变量 $event 变量用于访问原生DOM事件. <!DOCTYPE html> <html lang="zh"> <head> ...