「SDOI2017」树点涂色

我sb的不行了


其实一开始有一个类似动态dp的想法

每个点维护到lct树上到最浅点的颜色段数,然后维护一个\(mx_{0,1}\)也就是是否用虚儿子的最大颜色

用个set维护一下虚儿子

但是啊,我发现搞这个区间改颜色的时候,虚儿子好像得用树套树维护,我当场就不行了...


每个点如果维护到根的颜色段数\(f\)

然后发现啊,这个你如果用一个lct的一个子树维护同一种颜色,在你access的时候实变虚或者虚变实对子树有一个+1或者-1

然后额外在外面开一个线段树维护子树加减,每次access的时候操作

然后这个颜色段比较特殊,链的颜色个数可以\(f_u+f_v-f_{lca(u,v)}*2+1\),这个简单讨论一下就好了

操作3就是区间最大值


Code:

#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using std::max;
template <class T>
void read(T &x)
{x=0;char c=getchar();while(!isdigit(c)) c=getchar();while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
const int N=1e5+10;
int n,m;
int head[N],to[N<<1],Next[N<<1],cnt;
void add(int u,int v)
{to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
}
int mx[N<<2],tag[N<<2];
int dfn[N],low[N],dep[N],yuy[N],f[20][N],dfsclock;
int LCA(int x,int y)
{if(dep[x]<dep[y]) std::swap(x,y);for(int i=18;~i;i--)if(dep[f[i][x]]>=dep[y])x=f[i][x];if(x==y) return x;for(int i=18;~i;i--)if(f[i][x]!=f[i][y])x=f[i][x],y=f[i][y];return f[0][x];
}
void pushdown(int id)
{if(tag[id]){tag[id<<1]+=tag[id];tag[id<<1|1]+=tag[id];mx[id<<1]+=tag[id];mx[id<<1|1]+=tag[id];tag[id]=0;}
}
void build(int id,int l,int r)
{if(l==r) {mx[id]=yuy[l];return;}int mid=l+r>>1;build(id<<1,l,mid),build(id<<1|1,mid+1,r);mx[id]=max(mx[id<<1],mx[id<<1|1]);
}
void modify(int id,int L,int R,int l,int r,int d)
{if(l==L&&r==R){mx[id]+=d;tag[id]+=d;return;}pushdown(id);int Mid=L+R>>1;if(r<=Mid) modify(id<<1,L,Mid,l,r,d);else if(l>Mid) modify(id<<1|1,Mid+1,R,l,r,d);else modify(id<<1,L,Mid,l,Mid,d),modify(id<<1|1,Mid+1,R,Mid+1,r,d);mx[id]=max(mx[id<<1],mx[id<<1|1]);
}
int query(int id,int l,int r,int p)
{if(l==r) return mx[id];pushdown(id);int mid=l+r>>1;if(p<=mid) return query(id<<1,l,mid,p);else return query(id<<1|1,mid+1,r,p);
}
int query(int id,int L,int R,int l,int r)
{if(L==l&&R==r) return mx[id];pushdown(id);int Mid=L+R>>1;if(r<=Mid) return query(id<<1,L,Mid,l,r);else if(l>Mid) return query(id<<1|1,Mid+1,R,l,r);else return max(query(id<<1,L,Mid,l,Mid),query(id<<1|1,Mid+1,R,Mid+1,r));
}
int ch[N][2],par[N],Lef[N];
#define fa par[now]
#define ls ch[now][0]
#define rs ch[now][1]
bool isroot(int now){return ch[fa][0]==now||ch[fa][1]==now;}
int identity(int now){return ch[fa][1]==now;}
void connect(int f,int now,int typ){ch[fa=f][typ]=now;}
void updata(int now)
{Lef[now]=now;if(ls) Lef[now]=Lef[ls];
}
void Rotate(int now)
{int typ=identity(now),p=fa;connect(p,ch[now][typ^1],typ);if(isroot(p)) connect(par[p],now,identity(p));else fa=par[p];connect(now,p,typ^1);updata(p),updata(now);
}
void splay(int now)
{for(;isroot(now);Rotate(now))if(isroot(fa))Rotate(identity(fa)^identity(now)?now:fa);
}
void access(int now)
{for(int las=0;now;las=now,now=fa){splay(now);if(rs)modify(1,1,n,dfn[Lef[rs]],low[Lef[rs]],1);if(las)modify(1,1,n,dfn[Lef[las]],low[Lef[las]],-1);rs=las;updata(now);}
}
void dfs(int now,int dis)
{dfn[now]=++dfsclock;yuy[dfsclock]=dis;dep[now]=dep[par[now]=f[0][now]]+1;for(int i=1;f[i-1][now];i++) f[i][now]=f[i-1][f[i-1][now]];for(int v,i=head[now];i;i=Next[i])if((v=to[i])!=f[0][now])f[0][v]=now,dfs(v,dis+1);low[now]=dfsclock;
}
int main()
{read(n),read(m);for(int u,v,i=1;i<n;i++) read(u),read(v),add(u,v),add(v,u);dfs(1,1);build(1,1,n);for(int op,x,y,i=1;i<=m;i++){read(op),read(x);if(op==1) access(x);else if(op==2){read(y);printf("%d\n",query(1,1,n,dfn[x])+query(1,1,n,dfn[y])-(query(1,1,n,dfn[LCA(x,y)])<<1)+1);}elseprintf("%d\n",query(1,1,n,dfn[x],low[x]));}return 0;
}

2019.4.10

转载于:https://www.cnblogs.com/butterflydew/p/10681339.html

「SDOI2017」树点涂色 解题报告相关推荐

  1. 【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]

    树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MB [Submit][Status][Discuss] Description Bob有一棵n个点的有根树,其中 ...

  2. 「SCOI2014」方伯伯的 OJ 解题报告

    「SCOI2014」方伯伯的 OJ 和列队有点像,平衡树点分裂维护即可 但是需要额外用个set之类的对编号查找点的位置 插入完了后记得splay,删除时注意特判好多东西 Code: #include ...

  3. 「SCOI2015」小凸想跑步 解题报告

    「SCOI2015」小凸想跑步 最开始以为和多边形的重心有关,后来发现多边形的重心没啥好玩的性质 实际上你把面积小于的不等式列出来,发现是一次的,那么就可以半平面交了 Code: #include & ...

  4. BZOJ 4817: [Sdoi2017]树点涂色

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 273  Solved: 164 [Submit][Stat ...

  5. [Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 629  Solved: 371 [Submit][Stat ...

  6. 【线段树】【LCT】【LCA】树点涂色(luogu 3703)

    树点涂色 luogu 3703 题目大意 给出一棵树,每个节点的初始颜色不同,做若干操作: 1.在一个点到根节点路径上染上一种新的颜色 2.查询一条路径上有多少种不同的颜色 3.查询一个点x,使该点到 ...

  7. 【树链剖分】「ZJOI2008」树的统计

    前置知识 树链剖分的思想及能解决的问题 树链剖分用于将树分割成若干条链的形式,以维护树上路径的信息. 具体来说,将整棵树剖分为若干条链,使它组合成线性结构,然后用其他的数据结构维护信息. 树链剖分(树 ...

  8. BZOJ 4817: [Sdoi2017]树点涂色(LCT+树剖+线段树)

    题目描述 Bob有一棵 nn 个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. Bob ...

  9. Bzoj4817:[SDOI2017]树点涂色

    题面 Bzoj Sol 做个转化 最开始都是虚边 操作\(1\)就是\(LCT\)里的\(Access\)操作 求的就是路径上虚边的个数+1 然后就好办了 用树链剖分+线段树来维护每个点到根虚边的个数 ...

  10. bzoj4817: [Sdoi2017]树点涂色

    震惊!LCT还能这么用! 这个颜色修改的特点是点到根 搜刮一下性质,颜色从根到某个点是分层次单调增的,而且同一个点的两个不同儿子不会有相同颜色,也就是相同颜色的点是树上自上往下的一条链 前面这些都是次 ...

最新文章

  1. 用OpenCV玩《铁拳》!!!
  2. 《算法帝国》——华尔街,第一张多米诺骨牌
  3. Node项目之评分系统(一)- 基本介绍
  4. SAP 取月度期初库存和月度期末库存(历史库存)
  5. Lucene学习总结之七:Lucene搜索过程解析
  6. Avalonia跨平台入门第十二篇之动画效果
  7. Tomcat安装后没有出现tomcat主页
  8. pdf python 3.7编程快速入门 潘中强_无python基础,这些书籍可以帮您快速入门。
  9. java编程规范之java命名规范
  10. 计算机多媒体简历,[计算机个人简历模板范文]计算机多媒体专业个人简历
  11. RGB灯串24键红外遥控控制器芯片 SOP-8氛围灯小夜灯单片机芯片方案开发
  12. fastadmin 邮件配置
  13. 解除RAR和ZIP压缩包密码的不同方法
  14. 数控机床需要c语言程序吗,数控机床的编程有几种方法?
  15. [zt]给你的Mp4大换血,精选Touch里3年收集的900多首歌,经典不忍去的最新近流行的,与你共享~~...
  16. NVIDIA Jetson之UART功能开发
  17. 制定标准的重要性和意义_标准的重要性
  18. 计算机考研要考java吗_计算机二级考JAVA还是C?
  19. DeDeCMS v5.7 SP2正式版 前台任意用户密码修改 漏洞复现
  20. 牛掰!我是这么把博客粉丝转到公众号的

热门文章

  1. 拓端tecdat|R语言ARMA-EGARCH模型、集成预测算法对SPX实际波动率进行预测
  2. 拓端tecdat|R语言中小样本违反异方差性的线性回归
  3. 用python读取cifar-10与cifar-100图像数据
  4. 【Caffe代码解析】Blob
  5. python连接SQLServer数据库,执行给定的查询SQL语句,并返回查询结果数据
  6. Hive入门学习随笔(二)
  7. 为什么交叉熵损失函数可以用作逻辑回归的损失函数?
  8. 2021-06-22 超链接伪类
  9. C++ Segmentation fault 一般原因
  10. 悲观锁、乐观锁、单版本并发控制、多版本并发控制 关系