解析:增加三个变量lc(最左边的颜色),rc(最右边的颜色),sum(连续相同颜色区间段数)。然后就是区间合并的搞法。我就不详细解释了,估计你已经想到

如何做了。

代码

#include<cstdio>
#include<cstring>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn=;
int N,M,C[maxn];
struct lct
{
lct *fa,*son[];
int rev,c,setc,lc,rc,sum;
};
struct LCT
{
lct data[maxn];
lct *null;
void init(int Size=maxn-) //初始化
{
null=data; //null指向首元素
for(int i=;i<=Size;i++)
{
data[i].son[]=data[i].son[]=data[i].fa=null;
data[i].rev=;
data[i].c=data[i].lc=data[i].rc=C[i];
data[i].setc=-;
data[i].sum=;
}
null->c=null->lc=null->rc=-;
null->sum=;
}
void push_rev(lct* x)
{
if(x==null) return;
x->rev=!x->rev;
swap(x->son[],x->son[]);
swap(x->lc,x->rc);
}
void push_setc(lct* x,int setc)
{
if(x==null) return;
x->c=setc;
x->setc=setc;
x->lc=setc;
x->rc=setc;
x->sum=;
}
void pushdown(lct* x)
{
if(x->setc!=-)
{
push_setc(x->son[],x->setc);
push_setc(x->son[],x->setc);
x->setc=-;
}
if(x->rev)
{
push_rev(x->son[]);
push_rev(x->son[]);
x->rev=;
}
}
void pushup(lct* x)
{
if(x==null) return;
x->sum=;
if(x->son[]!=null)
{
x->sum+=x->son[]->sum;
if(x->son[]->rc==x->c) x->sum--;
}
if(x->son[]!=null)
{
x->sum+=x->son[]->sum;
if(x->son[]->lc==x->c) x->sum--;
}
x->lc=x->c;
if(x->son[]!=null) x->lc=x->son[]->lc;
x->rc=x->c;
if(x->son[]!=null) x->rc=x->son[]->rc;
}
bool Same(lct* x,lct* &y) //判断x和x的父亲是否在同一树里
{
return (y=x->fa)!=null&&(y->son[]==x||y->son[]==x);
}
void Rotate(lct* x,int d) //翻转
{
lct* y=x->fa; //x的父亲
y->son[d^]=x->son[d];
if(x->son[d]!=null) x->son[d]->fa=y; //x的子节点的父亲指向y
x->fa=y->fa; //连接
if(y->fa->son[]==y) x->fa->son[]=x;
else if(y->fa->son[]==y) x->fa->son[]=x;
x->son[d]=y;
y->fa=x;
}
void Splay(lct* x)
{
pushdown(x); //清除标记
lct* y;
while(Same(x,y)) //没有到树的最顶点
{
pushdown(y);
pushdown(x);
Rotate(x,y->son[]==x); //翻转
pushup(y);
pushup(x);
}
}
lct* Access(lct* u) //打通路径,返回的是根
{
lct *v=null;
for(;u!=null;u=u->fa)
{
Splay(u);
u->son[]=v;
pushup(v=u);
}
return v;
}
lct* GetRoot(lct* x) //得到根
{
for(x=Access(x);pushdown(x),x->son[]!=null;x=x->son[]) pushup(x);
return x;
}
void MakeRoot(lct* x) //使x成为根
{
Access(x);
Splay(x);
push_rev(x);
}
void Link(lct* x,lct* y) //连接两个点
{
MakeRoot(x);
x->fa=y;
Access(x);
}
void Cut(lct* x,lct* y) //断开两个点
{
MakeRoot(x);
Access(y);
Splay(y);
y->son[]->fa=null;
y->son[]=null;
}
void SetC(lct* x,lct* y,int setc)
{
MakeRoot(x);
push_setc(Access(y),setc);
}
int Query(lct* x,lct* y)
{
MakeRoot(x);
Access(y);
Splay(y);
return y->sum;
}
}A;
int main()
{
scanf("%d%d",&N,&M);
for(int i=;i<=N;i++) scanf("%d",&C[i]);
A.init(N);
int x,y;
for(int i=;i<N;i++)
{
scanf("%d%d",&x,&y);
A.Link(A.data+x,A.data+y);
}
char op[];
int c;
while(M--)
{
scanf("%s%d%d",op,&x,&y);
if(op[]=='C') scanf("%d",&c);
if(op[]=='C') A.SetC(A.data+x,A.data+y,c);
else printf("%d\n",A.Query(A.data+x,A.data+y));
}
return ;
}

bzoj2243-染色(动态树lct)的更多相关文章

  1. hdu 5398 动态树LCT

    GCD Tree Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Su ...

  2. hdu 5002 (动态树lct)

    Tree Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submi ...

  3. 动态树LCT小结

    最开始看动态树不知道找了多少资料,总感觉不能完全理解.但其实理解了就是那么一回事...动态树在某种意思上来说跟树链剖分很相似,都是为了解决序列问题,树链剖分由于树的形态是不变的,所以可以通过预处理节点 ...

  4. bzoj2049-洞穴勘测(动态树lct模板题)

    Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好 ...

  5. [模板] 动态树/LCT

    简介 LCT是一种数据结构, 可以维护树的动态加边, 删边, 维护链上信息(满足结合律), 单次操作时间复杂度 \(O(\log n)\).(不会证) 思想类似树链剖分, 因为splay可以换根, 用 ...

  6. 动态树LCT(Link-cut-tree)总结+模板题+各种题目

    一.理解LCT的工作原理 先看一道例题: 让你维护一棵给定的树,需要支持下面两种操作: Change x val:  令x点的点权变为val Query x y:  计算x,y之间的唯一的最短路径的点 ...

  7. SPOJ OTOCI 动态树 LCT

    SPOJ OTOCI 裸的动态树问题. 回顾一下我们对树的认识. 最初,它是一个连通的无向的无环的图,然后我们发现由一个根出发进行BFS 会出现层次分明的树状图形. 然后根据树的递归和层次性质,我们得 ...

  8. HDU 4718 The LCIS on the Tree (动态树LCT)

    The LCIS on the Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Oth ...

  9. BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 (动态树LCT)

    2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 2843  Solved: 1519[Submi ...

  10. HDU 5002 Tree(动态树LCT)(2014 ACM/ICPC Asia Regional Anshan Online)

    Problem Description You are given a tree with N nodes which are numbered by integers 1..N. Each node ...

随机推荐

  1. Ext.window的close的问题

    以前每次都是用的hide,关闭后隐藏窗体,下一次点击再打开,这种方法在我的随笔里面有,可是现在遇到一个问题,我的窗体里面有个formpanel,formpanel每一项都有一个默认值,意思就是修改的时 ...

  2. WebService- 使用 CXF 开发 SOAP 服务

    选框架犹如选媳妇,选来选去,最后我还是选了“丑媳妇(CXF)”,为什么是它?因为 CXF 是 Apache 旗下的一款非常优秀的 WS 开源框架,具备轻量级的特性,而且能无缝整合到 Spring 中. ...

  3. Struts2 页面url请求怎样找action

    1.我们使用最原始的方法去查找action.不同注解. struts.xml文件先配置 <!-- 新闻信息action --> <action name="newsInfo ...

  4. 阿里云主机SSD实例磁盘测试及IO调度算法调整

    测试背景及环境说明 阿里云ECS 主机配置: 4C8G root@zabbix-master:~# grep -i "model name" /proc/cpuinfo model ...

  5. Javascript高级程序设计读书笔记(第三章)

    第3章 基本概念 3.4 数据类型 5种简单数据类型:undefined.boolean.number.null.string. typeof操作符,能返回下列某个字符串:“undefined”.“b ...

  6. Asp.Net中的消息处理---MSMQ系列学习(一)

    刚刚毕业一年,比较浮躁,上次面试被问到消息队列,觉得非常的惭愧因为不知道,所以下定决心一定要学会使用它.以前只是听说过有这么个东西,要说是什么,在什么场景下使用却是无从知晓,因为自己也确实没有在项目中 ...

  7. Canvas简单动画和像素处理

    动画 利用JavaScript,可以在canvas元素上很容易地产生动画效果. var posX = 20, posY = 100; setInterval(function() { context. ...

  8. ORACLE触发器概述之【行触发器】【weber出品】

    1. 行触发器的定义 行触发器是指执行DML操作时,每作用一行就触发一次的触发器.审计数据变化时,可以使用行触发器 2. 建立行触发器的语法如下: create or replace trigger ...

  9. WCF Service端Inspector

    问题 在使用WCF的过程中,有时候需要在service端截取client和service之间的消息来做一些如写log,检查message是否合法的操作. 那么如何才能实现呢? 解决方案 使用WCF提供 ...

  10. javaWeb RSA加密使用

      加密算法在各个网站运用很平常,今天整理代码的时候看到了我们项目中运用了RSA加密,就了解了一下. 先简单说一下RSA加密算法原理,RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但 ...