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. Linux环境编程之IPC进程间通信(五):Posix消息队列1

    对于管道和FIFO来说.必须应该先有读取者存在.否则先有写入者是没有意义的. 而消息队列则不同,它是一个消息链表,有足够写权限的线程可往别的队列中放置消息,有足够读权限的线程可从队列中取走消息.每一个 ...

  2. BZOJ2330:[SCOI2011]糖果(差分约束)

    Description 幼儿园里有N个小朋友,lxhgww老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果.但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的 ...

  3. 如何求出数组中最小(或者最大)的k个数(least k问题)

    输入n个整数,如何求出其中最小的k个数? 解法1. 当然最直观的思路是将数组排序,然后就可以找出其中最小的k个数了,时间复杂度以快速排序为例,是O(nlogn): 解法2. 借助划分(Partitio ...

  4. 404 Note Found 队-Alpha10

    目录 组员情况 组员1(组长):胡绪佩 组员2:胡青元 组员3:庄卉 组员4:家灿 组员5:凯琳 组员6:翟丹丹 组员7:何家伟 组员8:政演 组员9:黄鸿杰 组员10:刘一好 组员11:何宇恒 展示 ...

  5. 【问题解决】增加https后 phpcms 分页错误

    https://m.cnbuses.com/m.cnbuses.com/index.php?page=2查看分页方法 function pages()中有个pageurl 查看该方法,发现有类似htt ...

  6. Go语言之旅:基本类型

    原文地址:https://learn-linux.readthedocs.io 欢迎关注我们的公众号:小菜学编程 (coding-fan) Go 内置了以下基本类型: 布尔 bool 字符串 stri ...

  7. 轻量ORM-SqlRepoEx (十七)SqlRepoEx 2.30 版本更新说明

    .Net平台下兼容.NET Standard 2.0,一个实现以Lambda表达式转转换标准SQL语句,支持MySQL.SQL Server数据库方言,使用强类型操作数据的轻量级ORM工具,在减少魔法 ...

  8. MySQL8.0.12版本的数据库驱动

    jdbcDriver=com.mysql.cj.jdbc.DriverjdbcUrl=jdbc:mysql://127.0.0.1:3306/jtsys?useUnicode=true&cha ...

  9. vim内替换文件内容

    几个常用的方法如下: :%s/foo/bar/g 把全部foo替换为bar,全局替换 :s/foo/bar/g 当前行替换foo为bar :%s/foo/bar/gc 替换每个foo为bar,但需要确 ...

  10. Java职业规划

    java学习这一部分其实也算是今天的重点,这一部分用来回答很多群里的朋友所问过的问题,那就是我你是如何学习Java的,能不能给点建议?今天我是打算来点干货,因此咱们就不说一些学习方法和技巧了,直接来谈 ...