bzoj2243-染色(动态树lct)
解析:增加三个变量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)的更多相关文章
- hdu 5398 动态树LCT
GCD Tree Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Su ...
- hdu 5002 (动态树lct)
Tree Time Limit: 16000/8000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submi ...
- 动态树LCT小结
最开始看动态树不知道找了多少资料,总感觉不能完全理解.但其实理解了就是那么一回事...动态树在某种意思上来说跟树链剖分很相似,都是为了解决序列问题,树链剖分由于树的形态是不变的,所以可以通过预处理节点 ...
- bzoj2049-洞穴勘测(动态树lct模板题)
Description 辉辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好 ...
- [模板] 动态树/LCT
简介 LCT是一种数据结构, 可以维护树的动态加边, 删边, 维护链上信息(满足结合律), 单次操作时间复杂度 \(O(\log n)\).(不会证) 思想类似树链剖分, 因为splay可以换根, 用 ...
- 动态树LCT(Link-cut-tree)总结+模板题+各种题目
一.理解LCT的工作原理 先看一道例题: 让你维护一棵给定的树,需要支持下面两种操作: Change x val: 令x点的点权变为val Query x y: 计算x,y之间的唯一的最短路径的点 ...
- SPOJ OTOCI 动态树 LCT
SPOJ OTOCI 裸的动态树问题. 回顾一下我们对树的认识. 最初,它是一个连通的无向的无环的图,然后我们发现由一个根出发进行BFS 会出现层次分明的树状图形. 然后根据树的递归和层次性质,我们得 ...
- 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 ...
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 (动态树LCT)
2002: [Hnoi2010]Bounce 弹飞绵羊 Time Limit: 10 Sec Memory Limit: 259 MBSubmit: 2843 Solved: 1519[Submi ...
- 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 ...
随机推荐
- Ext.window的close的问题
以前每次都是用的hide,关闭后隐藏窗体,下一次点击再打开,这种方法在我的随笔里面有,可是现在遇到一个问题,我的窗体里面有个formpanel,formpanel每一项都有一个默认值,意思就是修改的时 ...
- WebService- 使用 CXF 开发 SOAP 服务
选框架犹如选媳妇,选来选去,最后我还是选了“丑媳妇(CXF)”,为什么是它?因为 CXF 是 Apache 旗下的一款非常优秀的 WS 开源框架,具备轻量级的特性,而且能无缝整合到 Spring 中. ...
- Struts2 页面url请求怎样找action
1.我们使用最原始的方法去查找action.不同注解. struts.xml文件先配置 <!-- 新闻信息action --> <action name="newsInfo ...
- 阿里云主机SSD实例磁盘测试及IO调度算法调整
测试背景及环境说明 阿里云ECS 主机配置: 4C8G root@zabbix-master:~# grep -i "model name" /proc/cpuinfo model ...
- Javascript高级程序设计读书笔记(第三章)
第3章 基本概念 3.4 数据类型 5种简单数据类型:undefined.boolean.number.null.string. typeof操作符,能返回下列某个字符串:“undefined”.“b ...
- Asp.Net中的消息处理---MSMQ系列学习(一)
刚刚毕业一年,比较浮躁,上次面试被问到消息队列,觉得非常的惭愧因为不知道,所以下定决心一定要学会使用它.以前只是听说过有这么个东西,要说是什么,在什么场景下使用却是无从知晓,因为自己也确实没有在项目中 ...
- Canvas简单动画和像素处理
动画 利用JavaScript,可以在canvas元素上很容易地产生动画效果. var posX = 20, posY = 100; setInterval(function() { context. ...
- ORACLE触发器概述之【行触发器】【weber出品】
1. 行触发器的定义 行触发器是指执行DML操作时,每作用一行就触发一次的触发器.审计数据变化时,可以使用行触发器 2. 建立行触发器的语法如下: create or replace trigger ...
- WCF Service端Inspector
问题 在使用WCF的过程中,有时候需要在service端截取client和service之间的消息来做一些如写log,检查message是否合法的操作. 那么如何才能实现呢? 解决方案 使用WCF提供 ...
- javaWeb RSA加密使用
加密算法在各个网站运用很平常,今天整理代码的时候看到了我们项目中运用了RSA加密,就了解了一下. 先简单说一下RSA加密算法原理,RSA算法基于一个十分简单的数论事实:将两个大质数相乘十分容易,但 ...