【bzoj2243】[SDOI2011]染色

2017年10月20日

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,表示x和y之间有一条无向边。

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

“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]之间。、

题解:

题目很好理解,它不是边染色,而是点染色,这个性质是比较好的,边染色还需要裂点。

看的题目就可以想到这是树链剖分模板题吧,套个裸的线段树合并,其实没有什么合并的

东西,发现一段线段的不同颜色,那么就需要记录左端点和右端点颜色,如果左区间右端

点和右区间左端颜色一样,那么总颜色-1,这个比较好理解的吧,然后记录一个该区间总

颜色数,就可以统计了。

程序比较结构化
两个dfs预处理,lca,线段树,询问处理+更新处理,就ok了,代码比较清晰。

 #include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#define N 100007
using namespace std; int n,m,sz=;
int cnt,head[N],next[N*],rea[N*];
int a[N];
int fa[N][],size[N],pos[N],bel[N],deep[N];
char ch[];
struct Node
{
int lc,rc,tag,num;
}tr[N*]; void add(int u,int v){next[++cnt]=head[u],head[u]=cnt,rea[cnt]=v;}
void dfs_init(int u)
{
size[u]=;
for (int i=;(<<i)<=deep[u];i++)
fa[u][i]=fa[fa[u][i-]][i-];
for (int i=head[u];i!=-;i=next[i])
{
int v=rea[i];
if (v==fa[u][]) continue;
deep[v]=deep[u]+;
fa[v][]=u;
dfs_init(v);
size[u]+=size[v];
}
}
void dfs_make(int u,int chain)
{
int k=;
pos[u]=++sz,bel[u]=chain;
for (int i=head[u];i!=-;i=next[i])
{
int v=rea[i];
if (deep[v]>deep[u]&&size[v]>size[k]) k=v;
}
if (k==) return;
dfs_make(k,chain);
for (int i=head[u];i!=-;i=next[i])
{
int v=rea[i];
if (deep[v]>deep[u]&&v!=k) dfs_make(v,v);
}
}
int lca(int a,int b)
{
if (deep[a]<deep[b]) swap(a,b);
int i;
for (i=;(<<i)<=deep[a];i++);
i--;
for (int j=i;j>=;j--)
if (deep[a]-(<<j)>=deep[b]) a=fa[a][j];
if (a==b) return a;
for (int j=i;j>=;j--)
if (fa[a][j]!=fa[b][j]) a=fa[a][j],b=fa[b][j];
return fa[a][];
}
void updata_down(int l,int r,int p)
{
int tag=tr[p].tag;tr[p].tag=-;
if (tag==-||l==r) return;
tr[p<<].num=tr[p<<|].num=;
tr[p<<].tag=tr[p<<|].tag=tag;
tr[p<<].lc=tr[p<<].rc=tag;
tr[p<<|].lc=tr[p<<|].rc=tag;
}
void updata_up(int l,int r,int p)
{
tr[p].lc=tr[p<<].lc,tr[p].rc=tr[p<<|].rc;
tr[p].num=tr[p<<].num+tr[p<<|].num;
if (tr[p<<].rc==tr[p<<|].lc) tr[p].num--;
}
void change(int l,int r,int p,int x,int y,int z)
{
updata_down(l,r,p);
if (l==x&&y==r)
{tr[p].num=,tr[p].lc=tr[p].rc=tr[p].tag=z;return;}
int mid=(l+r)>>;
if (y<=mid) change(l,mid,p<<,x,y,z);
else if (x>mid) change(mid+,r,p<<|,x,y,z);
else change(l,mid,p<<,x,mid,z),change(mid+,r,p<<|,mid+,y,z);
updata_up(l,r,p);
}
int query(int l,int r,int p,int x,int y)
{
updata_down(l,r,p);
if (l==x&&y==r) return tr[p].num;
int mid=(l+r)>>,res;
if (y<=mid) res=query(l,mid,p<<,x,y);
else if (x>mid) res=query(mid+,r,p<<|,x,y);
else
{
res=query(l,mid,p<<,x,mid)+query(mid+,r,p<<|,mid+,y);
if (tr[p<<].rc==tr[p<<|].lc) res--;
}
return res;
}
int find(int l,int r,int p,int x)
{
updata_down(l,r,p);
if (l==r) return tr[p].lc;
int mid=(l+r)>>;
if (x<=mid) return find(l,mid,p<<,x);
else return find(mid+,r,p<<|,x);
}
int solvequery(int x,int fq)
{
int res=;
while(bel[x]!=bel[fq])
{
res+=query(,n,,pos[bel[x]],pos[x]);
if (find(,n,,pos[bel[x]])==find(,n,,pos[fa[bel[x]][]])) res--;
x=fa[bel[x]][];
}
res+=query(,n,,pos[fq],pos[x]);
return res;
}
void solvechange(int x,int fq,int z)
{
while(bel[x]!=bel[fq])
{
change(,n,,pos[bel[x]],pos[x],z);
x=fa[bel[x]][];
}
change(,n,,pos[fq],pos[x],z);
}
int main()
{
memset(head,-,sizeof(head));tr[].tag=-;
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%d",&a[i]);
int x,y,z;
for (int i=;i<n;i++)
{
scanf("%d%d",&x,&y);
add(x,y),add(y,x);
}
dfs_init();
dfs_make(,);
for (int i=;i<=n;i++)
change(,n,,pos[i],pos[i],a[i]);
//==============================================================
for (int i=;i<=m;i++)
{
scanf("%s",ch);
if (ch[]=='Q')
{
scanf("%d%d",&x,&y);
int par=lca(x,y);
printf("%d\n",solvequery(x,par)+solvequery(y,par)-);
}
else
{
scanf("%d%d%d",&x,&y,&z);
int par=lca(x,y);
solvechange(x,par,z),solvechange(y,par,z);
}
}
}

bzoj 2243 [SDOI2011]染色(树链剖分+线段树合并)的更多相关文章

  1. 2243: [SDOI2011]染色 树链剖分+线段树染色

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

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

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

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

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

  4. B20J_2243_[SDOI2011]染色_树链剖分+线段树

    B20J_2243_[SDOI2011]染色_树链剖分+线段树 一下午净调这题了,争取晚上多做几道. 题意: 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成 ...

  5. BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)

    题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...

  6. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

  7. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

  8. BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)

    前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...

  9. bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2852  Solved: 1668[Submit][Sta ...

  10. bzoj 2157: 旅游【树链剖分+线段树】

    裸的树链剖分+线段树 但是要注意一个地方--我WA了好几次才发现取完相反数之后max值和min值是要交换的-- #include<iostream> #include<cstdio& ...

随机推荐

  1. 201521123069 《Java程序设计》 第4周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. (1)文档注释(类注释.方法注释.属性注释.通用注释.) (2)多态性.instanceof ...

  2. 201521123013 《Java程序设计》第13周学习总结

    1. 本周学习总结 2. 书面作业 Q1. 网络基础 1.1 比较ping www.baidu.com与ping cec.jmu.edu.cn,分析返回结果有何不同?为什么会有这样的不同? ping值 ...

  3. 201521123024 java 第十周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 finally 题目4-2 1.1 截图你的提交结果(出现学 ...

  4. JSP第六篇【自定义标签之传统标签】

    为什么要使用自定义标签? JSTL标签库只提供了简单的输出等功能,没有实现任何的HTML代码封装,并且某些复杂类型转换,或者逻辑处理的时候,JSTL标签库完成不了,需要自定义标签! 编写自定义标签的步 ...

  5. Spring MVC 的文件下载

    在看Spring MVC文件下载之前请先看Spring MVC文件上传 地址:http://www.cnblogs.com/dj-blog/p/7535101.html 文件下载比较简单,在超链接中指 ...

  6. socket端口外网无法连接解决方法

    用socket做了个程序,本地测试没有问题,发布到服务器上时连接不上,用telnet测试连接失败 服务器上netstat -a 查看端口情况,127.0.0.1绑定端口9300处于监听状态,如下图: ...

  7. MySQL主从同步和读写分离的配置

    主服务器:192.168.1.126 从服务器:192.168.1.163 amoeba代理服务器:192.168.1.237 系统全部是CentOS 6.7 1.配置主从同步 1.1.修改主服务器( ...

  8. 在分布式数据库中CAP原理CAP+BASE

    本篇博文的内容均来源于网络,本人只是整理,仅供学习! 一.关系型数据库 关系型数据库遵循ACID规则 事务在英文中是transaction,和现实世界中的交易很类似,它有如下四个特性: 1.A (At ...

  9. python之路第五篇之装饰器:(进阶篇)

    装饰器: 学前必备知识: def f1(): print "f1" f1() #表示函数执行 f1 #表示函数,指向内存地址 f1 = lambda x: x + 1 f1() # ...

  10. ERROR! MySQL server PID file could not be found!的解决方法

    启动MySQL服务 [root@test vhosts]# /etc/init.d/mysqld restart 提示错误: ERROR! MySQL server PID file could no ...