【题目链接】

【思路】:

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

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. python与rpc服务

    什么是rpc 随着企业 IT 服务的不断发展,单台服务器逐渐无法承受用户日益增长的请求压力时,就需要多台服务器联合起来构成「服务集群」共同对外提供服务. 同时业务服务会随着产品需求的增多越来越肿,架构 ...

  2. @PostConstruct、@Autowired以及构造函数的执行顺序

    结论先行:构造函数 -> PostConstruct -> @Autowired 依次执行 由于项目需要启动时加载一个配置信息,所以想到了用@PostConstruct,如下所示: @Co ...

  3. 别傻傻不知道 == 和 equals 的区别【面试系列】

    ​ 关于这个问题,一般初中级面试中都会遇到,还记得我当初实习找工作的时候也遇到了这个问题,现在都还记得自己是怎么回答的:== 是基本类型比较,equals 是对象比较,不懂 hashCode,想起来简 ...

  4. Docker下构建centos7容器无法使用systemctl命令的解决办法

    最近在使用docker 构建centos7 容器时,发现无法使用systemctl 命令.后来万能的百度解决了问题,随记之以备后用. 解决办法: docker run --privileged -it ...

  5. ng 引入query

    ng 引入jquery 1.在项目中 npm install --save jquery 在对应组件中加入 import * as $ from "jquery";   在angu ...

  6. ReentrantLock 锁释放源码分析

    ReentrantLock 锁释放源码分析: 调用的是unlock 的方法: public void unlock() { sync.release(1); } 接下来分析release() 方法: ...

  7. WPF XAML Trigger中使用动画后 动画对象冻结的处理办法

    在编写XAML时 在Trigger中使用动画,在动画之后,动画对象就会被冻结,无法被其他动画或者属性改变. 处理办法有: 1 使用附加属性来添加动画 public static readonly De ...

  8. Angulaur导入其他位置的样式

    建立一个统一样式文件base-xxx.component.css 在需要导入样式的组件中,编辑.ts文件导入样式: 右侧是它的相对路径.

  9. 关于plupload组件无法拍照上传的解决方案

    关于plupload组件无法拍照上传的解决方案 其实是由于文件大小的问题 filters: { max_file_size: '2mb',//把这个调大些就可以了 前提是服务器支持 prevent_d ...

  10. 2019-11-29-dotnet-通过-WMI-获取指定进程的输入命令行

    原文:2019-11-29-dotnet-通过-WMI-获取指定进程的输入命令行 title author date CreateTime categories dotnet 通过 WMI 获取指定进 ...