[Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)
4817: [Sdoi2017]树点涂色
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 629 Solved: 371
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
Sample Output
题解:
其实这道题考的十分妙啊,对LCT的虚实边性质进行了充分的利用。


当lca和其中一个相同时,我们发现还是减多了,还是得加回来。
一条链的情况自己画图也是同理的。这样对于操作2就用线段树轻松维护了。
操作3????不就是线段树dfs序查询子树吗。
这样我们就神奇的利用了LCT的性质把一道看似树剖的题做成了LCT神题。。
AC代码:
过了样例直接交,一遍交过的酸爽
- # include <iostream>
- # include <cstdio>
- # include <cstring>
- using namespace std;
- const int N = 2e5 + ;
- int st[N],ed[N],fa[N],ch[N][],s[N << ],la[N << ],n,m,head[N],dt;
- struct Edge{
- int to,nex;
- }edge[N << ];
- void AddEdge(int u,int v)
- {
- edge[++dt] = (Edge){v,head[u]};
- head[u] = dt;
- }
- bool isroot(int x){return ch[fa[x]][] != x && ch[fa[x]][] != x;}
- void rotate(int x,int d)
- {
- int pre = fa[x],g = fa[pre],nex = ch[x][d];
- ch[pre][d ^ ] = nex;
- if(nex)fa[nex] = pre;
- fa[x] = g;
- if(!isroot(pre))ch[g][ch[g][] == pre] = x;
- ch[x][d] = pre;
- fa[pre] = x;
- }
- void splay(int x)
- {
- int pre,g;
- while(!isroot(x))
- {
- pre = fa[x],g = fa[pre];
- if(!isroot(pre) && !((ch[pre][] == x) ^ (ch[g][] == pre)))rotate(pre,ch[pre][] == x);
- rotate(x,ch[pre][] == x);
- }
- }
- int find(int x){while(ch[x][])x = ch[x][];return x;}
- void push(int x){s[x] = max(s[x << ],s[x << | ]);}
- void down(int x)
- {
- s[x << ] += la[x];s[x << | ] += la[x];
- la[x << | ] += la[x];la[x << ] += la[x];
- la[x] = ;
- }
- void updata(int L,int R,int l,int r,int rt,int d)
- {
- if(L <= l && r <= R){s[rt] += d;la[rt] += d;return;}
- down(rt);int mid = l + r >> ;
- if(L <= mid)updata(L,R,l,mid,rt << ,d);
- if(R > mid)updata(L,R,mid + ,r,rt << | ,d);
- push(rt);
- }
- int Query(int L,int R,int l,int r,int rt)
- {
- if(L <= l && r <= R)return s[rt];
- down(rt);int mid = l + r >> ;
- if(L > mid)return Query(L,R,mid + ,r,rt << | );
- if(R <= mid)return Query(L,R,l,mid,rt << );
- return max(Query(L,R,l,mid,rt << ),Query(L,R,mid + ,r,rt << | ));
- }
- int ask(int x){return Query(st[x],st[x],,n,);}
- void access(int x)
- {
- int y = ,t;
- while(x)
- {
- splay(x);
- if(t = find(ch[x][]))updata(st[t],ed[t],,n,,);
- ch[x][] = y;if(t = find(y))updata(st[t],ed[t],,n,,-);
- y = x;x = fa[x];
- }
- }
- int hson[N],sz[N],tot,top[N],dep[N],Fa[N],id[N];
- void dfs(int u)
- {
- sz[u] = ;
- for(int i = head[u];i;i = edge[i].nex)
- {
- if(sz[edge[i].to])continue;
- Fa[edge[i].to] = u;
- dep[edge[i].to] = dep[u] + ;
- dfs(edge[i].to);
- sz[u] += sz[edge[i].to];
- if(sz[hson[u]] < sz[edge[i].to])hson[u] = edge[i].to;
- }
- }
- void dfs(int u,int tp)
- {
- top[u] = tp;st[u] = ++tot;id[tot] = u;
- if(hson[u])dfs(hson[u],tp);
- for(int i = head[u];i;i = edge[i].nex)
- if(!st[edge[i].to])dfs(edge[i].to,edge[i].to);
- ed[u] = tot;
- }
- int lca(int x,int y)
- {
- while(top[x] != top[y])
- {
- if(dep[top[x]] < dep[top[y]])swap(x,y);
- x = Fa[top[x]];
- }
- return dep[x] < dep[y] ? x : y;
- }
- int Q1(int u,int v){return ask(u) + ask(v) - * ask(lca(u,v)) + ;}
- int Q2(int u){return Query(st[u],ed[u],,n,);}
- int main()
- {
- scanf("%d %d",&n,&m);int tp,x,y;
- for(int i = ;i < n;i++)
- {
- scanf("%d %d",&x,&y);
- AddEdge(x,y);AddEdge(y,x);
- }
- dfs();dfs(,);
- for(int i = ;i <= n;i++)updata(st[i],ed[i],,n,,),fa[i] = Fa[i];
- while(m--)
- {
- scanf("%d",&tp);
- if(tp == )scanf("%d",&x),access(x);
- if(tp == )scanf("%d %d",&x,&y),printf("%d\n",Q1(x,y));
- if(tp == )scanf("%d",&x),printf("%d\n",Q2(x));
- }
- }
[Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)的更多相关文章
- [BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)
4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 692 Solved: 408[Submit][Status ...
- BZOJ4817: [Sdoi2017]树点涂色(LCT)
Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...
- BZOJ4817[Sdoi2017]树点涂色——LCT+线段树
题目描述 Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色.Bob可能会进 ...
- 【BZOJ4817】[Sdoi2017]树点涂色 LCT+线段树
[BZOJ4817][Sdoi2017]树点涂色 Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路 ...
- [Sdoi2017]树点涂色 [lct 线段树]
[Sdoi2017]树点涂色 题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值 考场发现这个信息是可减的,但是没想到lct 特意设计成lct的形式! 如何求颜色数? ...
- BZOJ 4817 [SDOI2017]树点涂色 (LCT+线段树维护dfs序)
题目大意:略 涂色方式明显符合$LCT$里$access$操作的性质,相同颜色的节点在一条深度递增的链上 用$LCT$维护一个树上集合就好 因为它维护了树上集合,所以它别的啥都干不了了 发现树是静态的 ...
- 【bzoj4817】树点涂色 LCT+线段树+dfs序
Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...
- BZOJ4817 [Sdoi2017]树点涂色 【LCT + 线段树】
题目 Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色.Bob可能会进行这 ...
- 【bzoj4817】[Sdoi2017]树点涂色 LCT+LCA+线段树
题目描述 给出一棵n个点,以1为根的有根树,每个点初始染有互不相同的颜色.定义一条路径的权值为路径上的颜色种类数.现有m次操作,每次操作为以下三种之一: 1 x: 把点x到根节点的路径上所有的点染上一 ...
随机推荐
- php配置之include_path
在php.ini中配置include_path,可在引入文件时直接引入配置目录下的文件. 项目中就可以直接 引入/var/www/phpxwlib及/var/www/huicuiserver/libs ...
- UVA 10900 So you want to be a 2n-aire? 2元富翁 (数学期望,贪心)
题意:你一开始有1元钱,接下来又n<=30个问题,只需答对1个问题手上的钱就翻倍,最多答对n个,得到的钱是2n.而每个问题答对的概率是[t,1]之间平均分布,那么问最优情况下得到奖金的期望值是多 ...
- # Transition:添加弹出过渡效果
# Transition:添加弹出过渡效果 通过鼠标的单击.获得焦点,被点击或对元素任何改变中触发,并平滑地以动画效果改变CSS的属性值. W3C-transition MDN-transition ...
- C++#pragma pack指令
微软官方文档说#pragma pack 指令的作用是为结构.联合和类成员指定 pack 对齐.的主要作用就是改变编译器的内存对齐方式,这个指令在网络报文的处理中有着重要的作用,#pragma pack ...
- git 本地与远程仓库出现代码冲突解决方法
提交过程中报错: [python@heaven-00 Selesystem]$ git push -u origin masterUsername for 'https://github.com': ...
- 下拉列表事件 Dropdown iview
<Dropdown @on-click="export"> <Button icon='md-log-out'> 000l <Icon type=&q ...
- Eclipse Code Recommenders 自动补全(联想)神器
Eclipse Code Recommenders 可以在eclipse市场中下载.自动补全.模糊匹配.非常有用!
- 基于jquery的自定义显示消息数量
根据需求简单的实现一个小功能控件,暂时不支持扩展 $("xxxxxxx").iconCountPlugin(options, start, isOffset) {//三个参数,自定 ...
- Java 垃圾回收机制 (分代垃圾回收ZGC)
什么是自动垃圾回收? 自动垃圾回收是一种在堆内存中找出哪些对象在被使用,还有哪些对象没被使用,并且将后者删掉的机制.所谓使用中的对象(已引用对象),指的是程序中有指针指向的对象:而未使用中的对象(未引 ...
- windows中彻底卸载mysql
1)停止MySQL服务 打开控制面板→管理工具→服务(找到MySQL) 2)卸掉mysql server 打开控制面板→程序与功能→找到mysql server然后卸载 3)将mysql目录下的安装文 ...