Description

给定一棵有n个节点的无根树和m个操作,操作有2类:

1、将节点a到节点b路径上所有点都染成颜色c;

2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。

请你写一个程序依次完成这m个操作。

Input

第一行包含2个整数n和m,分别表示节点数和操作数;

第二行包含n个正整数表示n个节点的初始颜色

下面行每行包含两个整数x和y,表示xy之间有一条无向边。

下面行每行描述一个操作:

“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;

“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

Output

对于每个询问操作,输出一行答案。

Sample Input

6 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5

Sample Output

3
1
2

HINT

数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。


--->题目是复制过来的,感觉字体大小很奇怪啊...不管了,先把这道鸽了我好几天的题A掉

这道题呢主要是运用树链剖分和线段树的思想

我们用tree这个结构体来维护线段树中每个节点的左端点的颜色lc、右端点的颜色rc、区间标记col(别忘了标记下传)以及该区间颜色段的数量sum。

以下几点需要特别注意(本题难点):

  • 在区间合并的时候,如果左子树的右端和右子树的左端颜色一致,那么该区间sum--;

  • 在剖链的时候,如果上一条链的左端(即靠近根节点的一端,因为在建树的时候,线段树中越左边的位置越靠近根节点)颜色和当前剖到的链的右段(即远离根节点的一端,两链相交处)颜色一致,那么总颜色数sum--;

  • 当top[x]==top[y],即两点已经在同一条重链上时,两边端点的颜色都应与对应的点进行比较,如颜色一致,同样总颜色数sum--;

详情请见代码:

 #include<bits/stdc++.h>
using namespace std;
const int N=1e6+,inf=0x3f3f3f3f;
int next[*N],head[*N],to[N*],d[N],fa[N],v[*N],seg[*N],rev[*N],top[N],size[N],son[N],w[N];
int n;
int m,q,p,tot,cnt;
int sum,ma;
struct node{
int lc,rc,sum,col;
}tree[N];
void ADD(int k,int l,int r,int v)
{
tree[k].lc=tree[k].rc=v;
tree[k].sum=;
tree[k].col=v;
return ;
}
void pushdown(int k,int l,int r,int mid)
{
if(!tree[k].col)return ;
ADD(k<<,l,mid,tree[k].col);
ADD(k<<|,mid+,r,tree[k].col);
tree[k].col=;
}
void dfs1(int s,int ff)
{
size[s]=;d[s]=d[ff]+;fa[s]=ff;
for(int i=head[s],t;i,t=to[i];i=next[i])
{
if(t!=fa[s])
{
dfs1(t,s);
size[s]+=size[t];
if(size[t]>size[son[s]])son[s]=t;
}
}
}
void dfs2(int s)
{
if(son[s])
{
seg[son[s]]=++seg[];
top[son[s]]=top[s];
rev[seg[]]=son[s];
dfs2(son[s]);
}
for(int i=head[s],t;t=to[i],i;i=next[i])
{
if(!top[t])
{
seg[t]=++seg[];
rev[seg[]]=t;
top[t]=t;
dfs2(t);
}
}
}
void update(int k)
{
tree[k].sum=tree[k<<].sum+tree[k<<|].sum;
if(tree[k<<].rc==tree[k<<|].lc)tree[k].sum--;
tree[k].lc=tree[k<<].lc;
tree[k].rc=tree[k<<|].rc;
}
void build(int k,int l,int r)
{
if(l==r)
{
tree[k].lc=tree[k].rc=w[rev[l]];
tree[k].sum=;
return ;
}
int mid=l+r>>;
build(k<<,l,mid);
build(k<<|,mid+,r);
update(k);
}
node query2(int k,int l,int r,int x,int y)
{
if(l>=x&&r<=y)
{
return tree[k];
}
int mid=l+r>>;
pushdown(k,l,r,mid);
if(mid>=x)
{
if(mid<y)
{
node res,ll=query2(k<<,l,mid,x,y),rr=query2(k<<|,mid+,r,x,y);
res.sum=ll.sum+rr.sum+(ll.rc==rr.lc?-:);
res.lc=ll.lc;res.rc=rr.rc;
return res;
}
else return query2(k<<,l,mid,x,y);
}
else return query2(k<<|,mid+,r,x,y);
}
int query1(int x,int y)
{
//这里可能不是很好理解,但是把a、b当做现任和备胎可能会好想一些(机房大佬lhy指点)
int sum=,a=,b=;
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(d[fx]<d[fy])swap(x,y),swap(fx,fy),swap(a,b);
node res=query2(,,n,seg[fx],seg[x]);
sum+=res.sum;
if(res.rc==a)sum--;
a=res.lc;
x=fa[fx];fx=top[x];
}
if(d[x]>d[y])swap(x,y),swap(a,b);
node res=query2(,,n,seg[x],seg[y]);
sum+=res.sum;
if(res.lc==a) sum--;
if(res.rc==b) sum--;
return sum;
}
int read()
{
int f=;char ch;
while((ch=getchar())<''||ch>'')
if(ch=='-')f=-;
int res=ch-'';
while((ch=getchar())>=''&&ch<='')
res=res*+ch-'';
return res*f;
}
void write(int x)
{
if(x<)
{
putchar('-');
x=-x;
}
if(x>)write(x/);
putchar(x%+'');
}
void add(int x,int y)
{
next[++tot]=head[x];
head[x]=tot;
to[tot]=y;
}
void change2(int k,int l,int r,int x,int y,int v)
{
if(l>=x&&r<=y)return ADD(k,l,r,v);
int mid=l+r>>;
pushdown(k,l,r,mid);
if(mid>=x)change2(k<<,l,mid,x,y,v);
if(mid<y)change2(k<<|,mid+,r,x,y,v);
update(k);
}
void change1(int x,int y,int v)
{
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(d[fx]<d[fy])swap(x,y),swap(fx,fy);
change2(,,n,seg[fx],seg[x],v);
x=fa[fx];fx=top[x];
}
if(d[x]>d[y])swap(x,y);
change2(,,n,seg[x],seg[y],v);
}
int main()
{
n=read();m=read();
for(int i=;i<=n;i++)w[i]=read();
for(int i=;i<n;i++)
{
int x,y;
x=read();y=read();
add(x,y);add(y,x);
}
dfs1(,);
seg[]=top[]=rev[]=seg[]=;
dfs2();
build(,,n);
while(m--)
{
char ch;int a,b;
while((ch=getchar())<'A'||ch>'Z');
//这个地方读入一定要小心!我的爆零经验就是前车之鉴!!!
a=read();b=read();
if(ch=='C')
{
int c;c=read();
change1(a,b,c);
}
else
{
write(query1(a,b));
putchar('\n');
}
}
return ;
}
//硬生生凑个200行 ~(~ ̄▽ ̄)~

[SDOI2011]染色(信息学奥赛一本通 1563)(洛谷 2486)的更多相关文章

  1. BZOJ2243 洛谷2486 [SDOI2011]染色 树链剖分

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ2243 题目传送门 - 洛谷2486 题意概括 一棵树,共n个节点. 让你支持以下两种操作,共m次操 ...

  2. $ybt\ 【信息学奥赛一本通】题解目录$

    [信息学奥赛一本通]题解目录 $ \large -> OJ$ $ problem1000 $ \(Answer\) - > $ \large 1000$ $ problem1001 $ \ ...

  3. 「SDOI2014」旅行(信息学奥赛一本通 1564)(洛谷 3313)

    题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我 ...

  4. 【03NOIP普及组】麦森数(信息学奥赛一本通 1925)(洛谷 1045)

    [题目描述] 形如2P-1的素数称为麦森数,这时P一定也是个素数.但反过来不一定,即如果P是个素数,2P-1不一定也是素数.到1998年底,人们已找到了37个麦森数.最大的一个是P=3021377,它 ...

  5. 【00NOIP普及组】计算器的改良(信息学奥赛一本通 1910)(洛谷 1022)

    [题目描述] NCL是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一元一次方程的功能.实验室将这个任务交给了一个刚进入的新手ZL先 ...

  6. 【00NOIP普及组】税收与补贴问题(信息学奥赛一本通 1911)( 洛谷 1023)

    [题目描述] 每样商品的价格越低,其销量就会相应增大.现已知某种商品的成本及其在若干价位上的销量(产品不会低于成本销售),并假设相邻价位间销量的变化是线性的且在价格高于给 定的最高价位后,销量以某固定 ...

  7. 食物链【NOI2001】(信息学奥赛一本通 1390)

    [题目描述] 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种 ...

  8. 【NOI2002】荒岛野人(信息学奥赛一本通 1637)(洛谷 2421)

    题目描述 克里特岛以野人群居而著称.岛上有排列成环行的M个山洞.这些山洞顺时针编号为1,2,…,M.岛上住着N个野人,一开始依次住在山洞C1,C2,…,CN中,以后每年,第i个野人会沿顺时针向前走Pi ...

  9. 【09NOIP提高组】Hankson 的趣味题(信息学奥赛一本通 1856)(洛谷 1072)

    题目描述 Hanks 博士是BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫Hankson.现在,刚刚放学回家的Hankson 正在思考一个有趣的问题.今天在课堂上,老师讲解了如何求 ...

随机推荐

  1. SUSE12Sp3-使用Docker导入镜像并安装redis,zookeeper,kafka

    首先在另外一台联网电脑拉取最新的redis,zookeeper,kafka镜像 docker pull redis docker pull zookeeper docker pull wurstmei ...

  2. C#读写修改设置调整UVC摄像头画面-滚动

    有时,我们需要在C#代码中对摄像头的滚动进行读和写,并立即生效.如何实现呢? 建立基于SharpCamera的项目 首先,请根据之前的一篇博文 点击这里 中的说明,建立基于SharpCamera的摄像 ...

  3. ffmpeg开发文档

    libavcodec - 编码解码器 libavdevice - 输入输出设备的支持 libavfilter - 视音频滤镜支持 libavformat - 视音频等格式的解析 libavutil - ...

  4. Spring Security实现OAuth2.0授权服务 - 进阶版

    <Spring Security实现OAuth2.0授权服务 - 基础版>介绍了如何使用Spring Security实现OAuth2.0授权和资源保护,但是使用的都是Spring Sec ...

  5. API之Scanner,Random,ArrayList基础运用。重点是ArrayList

    有关API的这些类可以参考JDK的官方中文文档,看我的另一篇文章有下载==> https://www.cnblogs.com/gz18221/p/11968505.html<==文章地址 ...

  6. vue组件4 利用slot将内容传递给组件

    除了将数据作为prop传入到组件中,vue也允许传入HTML 父组件中的子组件:<custom-button>点我<custom-button/> custom-button子 ...

  7. 英文INSURAUNCE保险INSURAUNCE词汇

    世界保险INSURAUNCE 人类社会从开始就面临着自然灾害和意外事故的侵扰,在与大自然抗争的过程中,古代人们就萌生了对付灾害事故的保险思想和原始形态的保险方法.公元前2500年前后,古巴比伦王国国王 ...

  8. etcd和flannel实现docker跨物理机通信

    实验目标 跨物理机的容器之间能直接访问docker通过Flannel可以实现各容器间的相互通信,即宿主机和容器,容器和容器之间都能相互通信 实验环境 192.168.3.50 //etcd.flann ...

  9. linux下apache和tomcat整合

    一 Apache与Tomcat比较联系 apache支持静态页,tomcat支持动态的,比如servlet等. 一般使用apache+tomcat的话,apache只是作为一个转发,对jsp的处理是由 ...

  10. 算法dfs——二叉搜索树中最接近的值 II

    901. 二叉搜索树中最接近的值 II 中文 English 给定一棵非空二叉搜索树以及一个target值,找到 BST 中最接近给定值的 k 个数. 样例 样例 1: 输入: {1} 0.00000 ...