LG传送门

我写这道题的题解主要是因为洛谷上的题解要么讲的不清要么代码丑滑稽,导致初学时的我调了很久,所以想发个题解方便后来人。

由于要维护的信息还是具有区间可加性,只需要记录一下每个区间的左右端点颜色,就可以用树剖+线段树维护。

还不会的同学可以看我的树链剖分总结线段树总结

废话不多说直接上代码:看的时候注意一下upd(update)、psu(pushup)、qry(query)、qry0四个函数就好了。

#include<cstdio>
#define R register
#define I inline
using namespace std;
const int S=100003,N=200003,M=400003;
int h[S],s[N],g[N],d[S],t[S],p[S],q[S],r[S],f[S],w[S],u[S],o[M],v[M],a[M],b[M],c,e,n;
I void swp(int &x,int &y){x^=y,y^=x,x^=y;}
I void add(int x,int y){s[++c]=h[x],h[x]=c,g[c]=y;}
I void upd(int k,int z){o[k]=1,v[k]=a[k]=b[k]=z;}
I void psu(int k,int p,int q){
o[k]=o[p]+o[q],a[k]=a[p],b[k]=b[q];
if(b[p]==a[q]) --o[k];
}
I void psd(int k){if(v[k]){R int p=k<<1,q=p|1,z=v[k]; upd(p,z),upd(q,z),v[k]=0;}}
void bld(int k,int l,int r){
if(l==r){o[k]=1,a[k]=b[k]=u[l]; return ;}
R int p=k<<1,q=p|1,m=l+r>>1;
bld(p,l,m),bld(q,m+1,r),psu(k,p,q);
}
void mdf(int k,int l,int r,int x,int y,int z){
if(x<=l&&r<=y){upd(k,z); return ;}
R int p=k<<1,q=p|1,m=l+r>>1; psd(k);
if(x<=m) mdf(p,l,m,x,y,z);
if(y>m) mdf(q,m+1,r,x,y,z);
psu(k,p,q);
}
int qry(int k,int l,int r,int x,int y){
if(x<=l&&r<=y) return o[k];
R int p=k<<1,q=p|1,m=l+r>>1,o=0; psd(k);
if(x<=m) o+=qry(p,l,m,x,y);
if(y>m) o+=qry(q,m+1,r,x,y);
if(x<=m&&y>m) o-=b[p]==a[q];
return o;
}
int col(int k,int l,int r,int x){
if(l==r) return a[k];
R int p=k<<1,q=p|1,m=l+r>>1; psd(k);
if(x<=m) return col(p,l,m,x);
return col(q,m+1,r,x);
}
void dfs1(int x,int f){d[x]=d[f]+1,p[x]=f,t[x]=1;
for(R int i=h[x],y,m=0;i;i=s[i])
if((y=g[i])^f){dfs1(y,x),t[x]+=t[y];
if(t[y]>m) m=t[y],q[x]=y;
}
}
void dfs2(int x,int t){f[x]=++e,u[e]=w[x],r[x]=t;
if(!q[x]) return ; dfs2(q[x],t);
for(R int i=h[x],y;i;i=s[i])
if((y=g[i])^p[x]&&y^q[x]) dfs2(y,y);
}
I void mdf0(int x,int y,int z){
while(r[x]^r[y]){
if(d[r[x]]<d[r[y]]) swp(x,y);
mdf(1,1,n,f[r[x]],f[x],z),x=p[r[x]];
}
if(d[x]>d[y]) swp(x,y);
mdf(1,1,n,f[x],f[y],z);
}
I int qry0(int x,int y){
R int o=0,a=0,b=0;
while(r[x]^r[y]){
if(d[r[x]]<d[r[y]]) swp(x,y),swp(a,b); if(col(1,1,n,f[x])==a) --o;
o+=qry(1,1,n,f[r[x]],f[x]),a=col(1,1,n,f[r[x]]),x=p[r[x]];
}
if(d[x]>d[y]) swp(x,y),swp(a,b);
if(col(1,1,n,f[x])==a) --o; if(col(1,1,n,f[y])==b) --o;
return o+qry(1,1,n,f[x],f[y]);
}
int main(){
freopen("in","r",stdin);
freopen("a.out","w",stdout);
R int m,i,x,y,z; R char o[2];
for(scanf("%d%d",&n,&m),i=1;i<=n;++i) scanf("%d",&w[i]);
for(i=1;i<n;++i) scanf("%d%d",&x,&y),add(x,y),add(y,x);
dfs1(1,0),dfs2(1,1),bld(1,1,n);
for(i=1;i<=m;++i){scanf("%s%d%d",o,&x,&y);
if(o[0]=='C') scanf("%d",&z),mdf0(x,y,z);
else printf("%d\n",qry0(x,y));
}
return 0;
}

[SDOI2011]染色 树链剖分的更多相关文章

  1. BZOJ 2243: [SDOI2011]染色 [树链剖分]

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

  2. bzoj-2243 2243: [SDOI2011]染色(树链剖分)

    题目链接: 2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6267  Solved: 2291 Descript ...

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

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

  4. Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树

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

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

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

  6. BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  7. BZOJ 2243: [SDOI2011]染色 树链剖分+线段树区间合并

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

  8. 2243: [SDOI2011]染色(树链剖分+线段树)

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

  9. Luogu P2486 [SDOI2011]染色(树链剖分+线段树合并)

    Luogu P2486 [SDOI2011]染色 题面 题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例: 6 5 2 2 1 2 1 1 1 ...

  10. [bzoj 2243]: [SDOI2011]染色 [树链剖分][线段树]

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

随机推荐

  1. [Noip2007]Core树网的核

    嘟嘟嘟 首先求树的直径两次bfs即可,实际上bfs就是最短路,因为树上路径是唯一的,所以用任何一种遍历方法都行(spfa和dijkstra当然也可以). 可以证明,只要求出任意一条直径就行了,为什么呢 ...

  2. SpringMVC整合FreeMarker实例

    FreeMarker作为模板引擎,是比较常用的. FreeMarker官方文档地址为:https://freemarker.apache.org/ 现在浏览器或者翻译工具这么多,对于英文方面,我想大多 ...

  3. PAT——1063. 计算谱半径

    在数学中,矩阵的“谱半径”是指其特征值的模集合的上确界.换言之,对于给定的n个复数空间的特征值{a1+b1i, ..., an+bni},它们的模为实部与虚部的平方和的开方,而“谱半径”就是最大模. ...

  4. [LuoguP1438]无聊的数列(差分+线段树/树状数组)

    \(Link\) \(\color{red}{\mathcal{Description}}\) 给你一个数列,要求支持单点查询\(and\)区间加等差数列. \(\color{red}{\mathca ...

  5. ASP.NET MVC & WebApi 中实现Cors来让Ajax可以跨域访问 (转载)

    什么是Cors? CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing).它允许浏览器向跨源服务器,发出XMLHttpReq ...

  6. jquery 查找已经选中的下拉框/select

    $("select[name='select_name']").find('option:selected').text(); $('#select_name option:sel ...

  7. 微服务前端开发框架React-Admin

    前言 React-Admin是基于React16.x.Ant Design3.x的管理系统架构. 采用前后端分离,内置了许多管理系统常用功能,通过一些脚本.封装帮助开发人员快速开发管理系统,集中精力处 ...

  8. js中的冒泡排序

    <!-- 冒泡排序:把一组数列按照一定的顺序进行排列,从大到小,或者从小到大 -->          // 控制循环的轮数          arr = [3,14,55,2,1,4,5 ...

  9. new和delete的三种形式详解

    一.new操作符.delete操作符 class String { public: String(const char *str="") { if(str== NULL) { da ...

  10. C++ primer第三章作业

    3.1节 练习3.1: 使用恰当的using声明重做1.4.1节(第11页)和2.6.2节(第67页)的练习 #ifdef 1 #include <iostream> using std: ...