【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,表示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]之间。、

题解:

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

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

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

点和右区间左端颜色一样,那么总颜色-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. 团队作业八-Beta版本冲刺计划及安排

    Beta版本冲刺计划及安排 目录: 1.介绍小组新加入的成员,他担任的角色 2.下一阶段需要改进完善的功能 3.下一阶段新增(或修改)的功能 4.需要改进的团队分工 5.需要改进的工具流程 6.冲刺的 ...

  2. 团队作业4——第一次项目冲刺(Alpha版本)4.24

    ·本次会议为第三次Scrum Meeting会议~ ·本次会议项目经理召开时间为15:00,在教学楼教室召开,召开时长约30分钟,探讨了昨日任务的进展.遇到的困难以及后续所要开展的工作. 1.站立式会 ...

  3. 201521123108 《Java程序设计》第6周学习总结

    本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 书面作业 2.1. clone方法 1.1 Object对象中的 ...

  4. 201521123064 《Java程序设计》第2周学习总结

    1. 本章学习总结 1.学会使用码云管理代码,包括将本地的代码上传至码云,和将码云上的项目保存至本地. 2.将码云上项目保存至本地的过程中,若eclipse窗口中已有同名项目,则导入的过程中可能会出错 ...

  5. 201521123036 《Java程序设计》第11周学习总结

    本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. 书面作业 本次PTA作业题集多线程 互斥访问与同步访问 完成题集4-4(互斥访问)与4-5(同步访问) 1.1 除了使用 ...

  6. java: Java中this和super的用法总结

    this this是自身的一个对象,代表对象本身,可以理解为:指向对象本身的一个指针. this的用法在java中大体可以分为3种: 1.普通的直接引用 这种就不用讲了,this相当于是指向当前对象本 ...

  7. 【翻译】基于web创建逼真的3D图形 | CSS技巧

    个人翻译小站:http://www.zcfy.cc/article/creating-photorealistic-3d-graphics-on-the-web-css-tricks-4039.htm ...

  8. java.lang.IllegalArgumentException: Result Maps collection already contains value for

    如果在SSM整合的时候出现以下的错误: 留意一下是不是既在Mybatis配置文件中加载了映射文件,又在Spring配置文件中使用扫描式去加载映射文件了.两者是不能够重合使用的! Caused by: ...

  9. IDEA运行编译后配置文件无法找到,或配置文件修改后无效的问题

    1.触发事件 今天正好在学习log4j,为了测试其配置文件log4j.properties中的各种配置,进行了频繁修改和程序启动以确认效果,因为是使用的IDEA建立的Web项目,接着问题就来了,配置文 ...

  10. STS安装

    在eclipse中安装spring tool Suite插件需要根据eclipse版本找到对应的spring tool Suite安装包. spring tool Suite 官网地址:http:// ...