题面

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

题解

线段树+树链剖分大水题

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

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

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

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

至于跳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. php 处理并发问题

    对于商品抢购等并发场景下,可能会出现超卖的现象,这时就需要解决并发所带来的这些问题了 在PHP语言中并没有原生的提供并发的解决方案,因此就需要借助其他方式来实现并发控制. 方案一:使用文件锁排它锁 f ...

  2. iOS 开发之 Xcode installation failed invalid argument!

    1.运行模拟器的时候 报出:installation failed invalid argument! 原因分析:我把Bundle indentifier 置为空了! http://stackover ...

  3. ★Linux命令行操作技巧(作为服务器端)

    1.统计某个目录下总共有多少个文件(递归统计所有子目录)ls -lR|grep "^-"|wc -l

  4. CentOS 7 NetworkManager Keeps Overwriting /etc/resolv.conf

    In CentOS or Red Hat Enterprise Linux (RHEL) 7, you can find your /etc/resolv.conf file, which holds ...

  5. 关于 iOS 分类(Category)的实现代码

    其实质是对一个类的扩充,对类扩充的方法有两种: (1)通过继承(经常用到) (2)通过分类 一个已知类Name 其头文件Name.h #import <Foundation/Foundation ...

  6. bzoj 2217 [Poi2011]Lollipop 乱搞 贪心

    2217: [Poi2011]Lollipop Time Limit: 15 Sec  Memory Limit: 64 MBSec  Special JudgeSubmit: 383  Solved ...

  7. Oauth认证协议

    原文地址腾讯QQ第三方登录的实现原理? Oauth当中的角色: 1.Service Provider(服务提供方): 服务提供方通常是网站,在这些网站当中存储着一些受限制的资源,如照片.视频.联系人列 ...

  8. HDU - 2112 HDU Today Dijkstra

    注意: 1.去重边 2.终点和起点一样,应当输出0 3.是无向图 AC代码 #include <cstdio> #include <cmath> #include <al ...

  9. UVA 1626 Brackets sequence 区间DP

    题意:给定一个括号序列,将它变成匹配的括号序列,可能多种答案任意输出一组即可.注意:输入可能是空串. 思路:D[i][j]表示区间[i, j]至少需要匹配的括号数,转移方程D[i][j] = min( ...

  10. JVM笔记3-java内存区域之运行时常量池

    1.运行时常量池属于线程共享区中的方法区. 2.运行时常量池用于编译期生成的各种自变量,符号引用,这部分内用将在类加载后接入方法区的运行时常量池中存放. 看如下代码所示,如图: public clas ...