【题目链接】

【思路】:

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

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. C++对象布局

    <C++应用程序性能优化><深度探索C++对象模型>笔记 #include<iostream> using namespace std; class student ...

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

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

  3. ASP.NET Core 中的 依赖注入介绍

    ASP.NET Core 依赖注入 HomeController public class HomeController : Controller { private IStudentReposito ...

  4. AtCoder Grand Contest 037题解

    传送门 \(A\) 直接把每个字母作为一个字符串,如果某个串和它前面的相同,那么就把这个字母和它后面那个字母接起来.然而我并不会证明这个贪心的正确性 //quming #include<bits ...

  5. [LeetCode] 731. My Calendar II 我的日历之二

    Implement a MyCalendarTwo class to store your events. A new event can be added if adding the event w ...

  6. JAVA SE11环境变量配置(Windows)

    附上:03. 安装环境:Windows · IntelliJ IDEA Tutorial 附上:使用调试功能进行 Java debug 附上:Linux(Deepin)下配置java8 - L1412 ...

  7. Pytorch循环神经网络LSTM时间序列预测风速

    #时间序列预测分析就是利用过去一段时间内某事件时间的特征来预测未来一段时间内该事件的特征.这是一类相对比较复杂的预测建模问题,和回归分析模型的预测不同,时间序列模型是依赖于事件发生的先后顺序的,同样大 ...

  8. C++ 版本ORM访问数据库之ODB访问oracle的Demo(三)

    ODB的组成部分: 1: 操作系统的ODB编译器 2: odb核心库libodb 3: 各种数据库的相关链接库 使用ODB访问数据需要的库和头文件(不懂, 请看https://www.cnblogs. ...

  9. Visual Studio 调试系列9 调试器提示和技巧

    系列目录     [已更新最新开发文章,点击查看详细] 01 固定数据提示 如果你在调试时,经常将鼠标悬停在数据提示上,就可能想固定变量的数据提示,方便自己随时查看. 即使在重新启动后,固定的变量也能 ...

  10. [Powershell]导出指定的定时计划任务

    <# .NOTES =========================================================================== Created wit ...