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. IDEA连接MySQL数据库报错08001

    今天在使用IDEA时连接数据库发生错误,所以用其自带的尝试连接得到如下错误:Connection to test@127.0.0.1 failed.[08001] Could not create c ...

  2. APS.NET MVC + EF (05)---控制器

    Controller(控制器)在ASP.NET MVC中负责控制所有客户端与服务端的交互,并且负责协调Model与View之间数据传递,是ASP.NET MVC框架核心.Controller为ASP. ...

  3. mybatis关联映射一对一

    在项目开发中,会存在一对一的关系,比如一个人只有一个身份证,一个身份证只能给一个人使用,这就是一对一关系.一对一关系使用主外键关联. table.sql,在数据库中创建如下两个表并插入数据 CREAT ...

  4. SpringCloud之监控数据聚合Turbine

    前言 SpringCloud 是微服务中的翘楚,最佳的落地方案. 使用 SpringCloud 的 Hystrix Dashboard 组件可以监控单个应用服务的调用情况,但如果是集群环境,可能就 不 ...

  5. backtrace() returns only one stack frame

    参考: 在Linux中如何利用backtrace信息解决程序崩溃的问题 linux 打印堆栈方法 https://devtalk.nvidia.com/default/topic/987279/jet ...

  6. java-spring基于redis单机版(redisTemplate)实现的分布式锁+redis消息队列,可用于秒杀,定时器,高并发,抢购

    此教程不涉及整合spring整合redis,可另行查阅资料教程. 代码: RedisLock package com.cashloan.analytics.utils; import org.slf4 ...

  7. Linux操作系统之用户权限,重定向,文件管理

    文件的权限 ls -al  ----->隐藏文件会以 .号开头 ls -ld :显示目录自身属性 ls -i 显示文件的索引号----每个文件都有一个对应的号码 ls -r 逆序显示 dr-xr ...

  8. mklink 文件夹链接 windows系统

    MS文档 https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/mklink 命令参数 mkl ...

  9. selenium+python自动化100-centos上搭建selenium启动chrome浏览器headless无界面模式

    环境准备 前言 selenium在windows机器上运行,每次会启动界面,运行很不稳定.于是想到用chrome来了的headless无界面模式,确实方便了不少. 为了提高自动化运行的效率和稳定性,于 ...

  10. oracle安装11g以及建账号等等

    Oracle 11g安装步骤详解 一.Oracle 下载 注意Oracle分成两个文件,下载完后,将两个文件解压到同一目录下即可. 路径名称中,最好不要出现中文,也不要出现空格等不规则字符. 官方下地 ...