题面

我们也要换个花样,这回提供洛谷的题面

题解

线段树+树链剖分大水题

维护颜色段的方法很简单呀。。。

维护当前区间内的颜色段个数,

以及当前区间左端和右端的颜色,

合并的时候考虑是否要减一下就行了

至于跳LCA进行Modify的时候稍微注意一下细节

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#define MAX 110000
#define lson (now<<1)
#define rson (now<<1|1)
using namespace std;
inline int read()
{
register int x=0,t=1;
register char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-'){t=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
return x*t;
}
struct Line
{
int v,next;
}e[MAX<<1];
int h[MAX],cnt=1;
struct Node
{
int c;
int lc,rc;
int ly;
}t[MAX<<2];
inline void Add(int u,int v)
{
e[cnt]=(Line){v,h[u]};
h[u]=cnt++;
}
int n,m,c[MAX],tim;
int dfn[MAX],dep[MAX],line[MAX],ff[MAX],size[MAX],hson[MAX],top[MAX];
void dfs1(int u,int fa)
{
size[u]=1;dep[u]=dep[fa]+1;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;
if(v==fa)continue;
ff[v]=u;
dfs1(v,u);
size[u]+=size[v];
if(size[v]>size[hson[u]])hson[u]=v;
}
}
void dfs2(int u,int tp)
{
top[u]=tp;dfn[u]=++tim;line[tim]=u;
if(hson[u])dfs2(hson[u],tp);
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;
if(v==hson[u]||v==ff[u])continue;
dfs2(v,v);
}
}
void pushup(int now)
{
t[now].c=t[lson].c+t[rson].c;
if(t[lson].rc==t[rson].lc)t[now].c--;
t[now].lc=t[lson].lc;
t[now].rc=t[rson].rc;
}
void pushdown(int now)
{
if(t[now].ly)
{
t[lson].ly=t[rson].ly=t[lson].lc=t[now].ly;
t[rson].lc=t[lson].rc=t[rson].rc=t[now].ly;
t[lson].c=t[rson].c=1;
t[now].ly=0;
}
}
void putlazy(int now,int ly)
{
t[now].c=1;
t[now].lc=t[now].rc=ly;
t[now].ly=ly;
}
void Build(int now,int l,int r)
{
if(l==r)
{
t[now].lc=t[now].rc=c[line[l]];
t[now].c=1;
return;
}
int mid=(l+r)>>1;
Build(lson,l,mid);Build(rson,mid+1,r);
pushup(now);
t[now].lc=t[lson].lc;
t[now].rc=t[rson].rc;
}
int getl(int now,int l,int r,int al)
{
if(al==l)return t[now].lc;
pushdown(now);
int mid=(l+r)>>1;
int re;
if(mid>=al)re=getl(lson,l,mid,al);
else re=getl(rson,mid+1,r,al);
pushup(now);
return re;
}
int getr(int now,int l,int r,int ar)
{
if(r==ar)return t[now].rc;
pushdown(now);
int mid=(l+r)>>1;
int re;
if(mid>=ar)re=getr(lson,l,mid,ar);
else re=getr(rson,mid+1,r,ar);
pushup(now);
return re;
}
int Query(int now,int l,int r,int al,int ar)
{
if(l==al&&r==ar)return t[now].c;
pushdown(now);
int mid=(l+r)>>1;
int re;
if(ar<=mid)re=Query(lson,l,mid,al,ar);
else if(al>mid)re=Query(rson,mid+1,r,al,ar);
else re=(Query(lson,l,mid,al,mid)+Query(rson,mid+1,r,mid+1,ar)-(t[lson].rc==t[rson].lc?1:0));
return re;
}
void Modify(int now,int l,int r,int al,int ar,int cc)
{
if(l==al&&r==ar)
{
putlazy(now,cc);return;
}
int mid=(l+r)>>1;
pushdown(now);
if(ar<=mid)Modify(lson,l,mid,al,ar,cc);
else if(al>mid)Modify(rson,mid+1,r,al,ar,cc);
else
{
Modify(lson,l,mid,al,mid,cc);
Modify(rson,mid+1,r,mid+1,ar,cc);
}
pushup(now);
}
int Answer(int u,int v)
{
int ans=0;
int lu=-1,lv=-1;
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])swap(u,v),swap(lu,lv);
int cl=getl(1,1,n,dfn[top[u]]),cr=getr(1,1,n,dfn[u]);
ans+=Query(1,1,n,dfn[top[u]],dfn[u]);
if(cr==lu)ans--;
lu=cl;
u=ff[top[u]];
}
if(dep[u]>dep[v])swap(u,v),swap(lu,lv);
ans+=Query(1,1,n,dfn[u],dfn[v]);
int cl=getl(1,1,n,dfn[u]),cr=getr(1,1,n,dfn[v]);
if(cl==lu)--ans;
if(cr==lv)--ans;
return ans;
}
void Change(int u,int v,int cc)
{
while(top[u]!=top[v])
{
if(dep[top[u]]<dep[top[v]])swap(u,v);
Modify(1,1,n,dfn[top[u]],dfn[u],cc);
u=ff[top[u]];
}
if(dep[u]>dep[v])swap(u,v);
Modify(1,1,n,dfn[u],dfn[v],cc);
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;++i)c[i]=read();
for(int i=1;i<n;++i)
{
int u=read(),v=read();
Add(u,v);Add(v,u);
}
dfs1(1,0);dfs2(1,1);
Build(1,1,n);
char ch[5];
while(m--)
{
scanf("%s",ch);
if(ch[0]=='C')
{
int a=read(),b=read(),c=read();
Change(a,b,c);
}
else
{
int a=read(),b=read();
printf("%d\n",Answer(a,b));
}
}
return 0;
}

【BZOJ2243】【SDOI2011】染色(树链剖分,线段树)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. BZOJ2243 (树链剖分+线段树)

    Problem 染色(BZOJ2243) 题目大意 给定一颗树,每个节点上有一种颜色. 要求支持两种操作: 操作1:将a->b上所有点染成一种颜色. 操作2:询问a->b上的颜色段数量. ...

  7. 【bzoj1959】[Ahoi2005]LANE 航线规划 树链剖分+线段树

    题目描述 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系. 星际空间站的Samuel II巨型计算 ...

  8. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  9. POJ3237 (树链剖分+线段树)

    Problem Tree (POJ3237) 题目大意 给定一颗树,有边权. 要求支持三种操作: 操作一:更改某条边的权值. 操作二:将某条路径上的边权取反. 操作三:询问某条路径上的最大权值. 解题 ...

  10. bzoj4034 (树链剖分+线段树)

    Problem T2 (bzoj4034 HAOI2015) 题目大意 给定一颗树,1为根节点,要求支持三种操作. 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

随机推荐

  1. python装饰器探究与参数的领取

    首先上原文, 现在,假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称之为"装饰器" ...

  2. es6变量声明和解构赋值

    /*声明: * 本文内容多为学习借鉴性内容,大部分非原创 * 特别感谢阮一峰的 ECMAScript6 入门,推荐大家学习 */ 一.es5变量声明的不足 1.变量提升和函数声明提升 es5的代码加载 ...

  3. Spring boot 整合redis单机版

       一.安装redis 这个不多说,网上有各种系统安装redis的操作, redis安装 二.创建sprigboot项目 这个也不多说,不会的前面有相关教程. 三.添加maven坐标 四.编写spr ...

  4. 剑指offer第三天

    21.栈的压入.弹出序列 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3, ...

  5. 【BZOJ1834】 网络扩容

    Time Limit: 1000 ms   Memory Limit: 128 MB Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费 ...

  6. Ubuntu17.10下启动Rancher

    1.安装Docker: 获取最新的docker安装包 wget -qO- https://get.docker.com/ | sh 2.启动docker后台服务: service docker sta ...

  7. yum源配置的三种方法

    (一)yum源概述 yum需要一个yum库,也就是yum源.默认情况下,CentOS就有一个yum源.在/etc/yum.repos.d/目录下有一些默认的配置文件(可以将这些文件移到/opt下,或者 ...

  8. Shell脚本——特殊符号

    1. # 井号(pound) 脚本文件运行时,使用的解释器. #!/bin/sh 其他时候表示注释. # This is a comment. 2. ~ 波浪号(tilde) 表示当前用户使用的hom ...

  9. eclipse导入/编译hadoop源代码

    1. 确保安装好JDK和eclipse 详细教程见: http://blog.csdn.net/kangdakangdaa/article/details/11364985 2. 安装 Subclip ...

  10. java中的mvc和三层结构究竟是什么关系

    一件事,要知其然往往很简单,要知其所以然通常不是那么容易,就如最近重新巩固spring的过程中,就觉得还有许多问题其实并不是十分明了. 屈指一算,手头上做过的正式项目也有了四五六七个了,不管用的数据库 ...