【XSY2534】【BZOJ4817】树点涂色 LCT 倍增 线段树 dfs序
题目大意
Bob有一棵\(n\)个点的有根树,其中\(1\)号点是根节点。Bob在每个点上涂了颜色,并且每个点上的颜色不同。定义一条路径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色。Bob可能会进行这几种操作:
\(1~x\):把点\(x\)到根节点的路径上所有的点染上一种没有用过的新颜色。
\(2~x~y\):求\(x\)到\(y\)的路径的权值。
\(3~x~y\):在以\(x\)为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。
Bob一共会进行\(m\)次操作
\(n,m\leq 100000\)
题解
注意到操作\(1\)就是\(access\)操作,可以用LCT维护。
设\(f_i=\)点\(i\)到根的路径权值,则操作\(2\)的答案为\(f_x+f_y-2f_{lca}+1\)。
如果只有操作\(1\)和操作\(2\)的话,就可以暴力往上跳,但是操作\(3\)就没那么好处理了。
所以我们可以用线段树+dfs序维护\(f_i\)
\(access\)切换虚实边时一棵子树的\(f\)全部\(+1\),另一棵子树的\(f\)全部\(-1\)
然后用倍增求LCA
时间复杂度:\(O(n\log^2n)\)
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
int n,m;
namespace seg
{
int s[4000010];
int t[4000010];
int n;
void init()
{
n=0;
memset(s,0,sizeof s);
memset(t,0,sizeof t);
}
void at(int x,int v)
{
s[x]+=v;
t[x]+=v;
}
void push(int x)
{
at(x*2,t[x]);
at(x*2+1,t[x]);
t[x]=0;
}
void add(int p,int l,int r,int v,int L,int R)
{
if(l<=L&&r>=R)
{
at(p,v);
return;
}
if(t[p])
push(p);
int mid=(L+R)>>1;
if(l<=mid)
add(p*2,l,r,v,L,mid);
if(r>mid)
add(p*2+1,l,r,v,mid+1,R);
s[p]=max(s[p*2],s[p*2+1]);
}
int query(int p,int l,int r,int L,int R)
{
if(l<=L&&r>=R)
return s[p];
if(t[p])
push(p);
int mid=(L+R)>>1;
int res=0;
if(l<=mid)
res=max(res,query(p*2,l,r,L,mid));
if(r>mid)
res=max(res,query(p*2+1,l,r,mid+1,R));
return res;
}
}
namespace tree
{
struct list
{
int v[200010];
int t[200010];
int h[100010];
int n;
list()
{
n=0;
memset(h,0,sizeof h);
}
void add(int x,int y)
{
n++;
v[n]=y;
t[n]=h[x];
h[x]=n;
}
};
list l;
int bg[100010];
int ed[100010];
int ti;
int f[100010][20];
int d[100010];
void init()
{
memset(f,0,sizeof f);
ti=0;
}
void dfs(int x,int fa,int dep)
{
bg[x]=++ti;
f[x][0]=fa;
d[x]=dep;
int i;
for(i=1;i<=19;i++)
f[x][i]=f[f[x][i-1]][i-1];
for(i=l.h[x];i;i=l.t[i])
if(l.v[i]!=fa)
dfs(l.v[i],x,dep+1);
ed[x]=ti;
}
int getlca(int x,int y)
{
if(d[x]<d[y])
swap(x,y);
int i;
for(i=19;i>=0;i--)
if(d[f[x][i]]>=d[y])
x=f[x][i];
if(x==y)
return x;
for(i=19;i>=0;i--)
if(f[x][i]!=f[y][i])
{
x=f[x][i];
y=f[y][i];
}
return f[x][0];
}
}
namespace lct
{
int f[100010];
int a[100010][2];
void init()
{
memset(f,0,sizeof f);
memset(a,0,sizeof a);
}
int root(int x)
{
return a[f[x]][0]!=x&&a[f[x]][1]!=x;
}
void rotate(int x)
{
if(root(x))
return;
int p=f[x];
int q=f[p];
int ps=(x==a[p][1]);
int qs=(p==a[q][1]);
int ch=a[x][ps^1];
if(!root(p))
a[q][qs]=x;
a[x][ps^1]=p;
a[p][ps]=ch;
if(ch)
f[ch]=p;
f[p]=x;
f[x]=q;
}
int splay(int x)
{
while(!root(x))
{
int p=f[x];
if(!root(p))
if((x==a[p][1])^(p==a[f[p]][1]))
rotate(p);
else
rotate(x);
rotate(x);
}
}
void access(int x)
{
int t=0;
int y=x,z;
while(x)
{
splay(x);
if(t)
{
while(a[t][0])
t=a[t][0];
splay(t);
seg::add(1,tree::bg[t],tree::ed[t],-1,1,n);
}
z=a[x][1];
a[x][1]=t;
if(z)
{
while(a[z][0])
z=a[z][0];
splay(z);
seg::add(1,tree::bg[z],tree::ed[z],1,1,n);
}
t=x;
x=f[x];
}
splay(y);
}
}
int main()
{
lct::init();
seg::init();
tree::init();
// freopen("bzoj4817.in","r",stdin);
// freopen("bzoj4817.out","w",stdout);
scanf("%d%d",&n,&m);
int i,op,x,y,ans;
for(i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
tree::l.add(x,y);
tree::l.add(y,x);
}
tree::dfs(1,0,1);
for(i=2;i<=n;i++)
lct::f[i]=tree::f[i][0];
for(i=1;i<=n;i++)
seg::add(1,tree::bg[i],tree::bg[i],tree::d[i],1,n);
for(i=1;i<=m;i++)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d",&x);
lct::access(x);
}
else if(op==2)
{
scanf("%d%d",&x,&y);
int lca=tree::getlca(x,y);
ans=seg::query(1,tree::bg[x],tree::bg[x],1,n)+
seg::query(1,tree::bg[y],tree::bg[y],1,n)-
2*seg::query(1,tree::bg[lca],tree::bg[lca],1,n)+1;
printf("%d\n",ans);
}
else
{
scanf("%d",&x);
ans=seg::query(1,tree::bg[x],tree::ed[x],1,n);
printf("%d\n",ans);
}
}
return 0;
}
【XSY2534】【BZOJ4817】树点涂色 LCT 倍增 线段树 dfs序的更多相关文章
- 【bzoj4817】[Sdoi2017]树点涂色 LCT+LCA+线段树
题目描述 给出一棵n个点,以1为根的有根树,每个点初始染有互不相同的颜色.定义一条路径的权值为路径上的颜色种类数.现有m次操作,每次操作为以下三种之一: 1 x: 把点x到根节点的路径上所有的点染上一 ...
- BZOJ 4817: [Sdoi2017]树点涂色 LCT+Access的性质+DFS序+线段树
Code: #include<bits/stdc++.h> #define maxn 200003 #define inf -1000000 using namespace std; vo ...
- LOJ2001 SDOI2017 树点涂色 LCT、线段树
传送门 注意到每一次\(1\ x\)操作相当于一次LCT中的access操作.由LCT复杂度证明可以知道access的总次数不会超过\(O(nlogn)\),我们只需要模拟这个access的过程并在其 ...
- 【BZOJ4817】[Sdoi2017]树点涂色 LCT+线段树
[BZOJ4817][Sdoi2017]树点涂色 Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路 ...
- [BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)
4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 692 Solved: 408[Submit][Status ...
- 【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]
树点涂色 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description Bob有一棵n个点的有根树,其中1 ...
- [SDOI2017][bzoj4817] 树点涂色 [LCT+线段树]
题面 传送门 思路 $LCT$ 我们发现,这个1操作,好像非常像$LCT$里面的$Access$啊~ 那么我们尝试把$Access$操作魔改成本题中的涂色 我们令$LCT$中的每一个$splay$链代 ...
- [Sdoi2017]树点涂色 [lct 线段树]
[Sdoi2017]树点涂色 题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值 考场发现这个信息是可减的,但是没想到lct 特意设计成lct的形式! 如何求颜色数? ...
- P3703 [SDOI2017]树点涂色 LCT维护颜色+线段树维护dfs序+倍增LCA
\(\color{#0066ff}{ 题目描述 }\) Bob有一棵\(n\)个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点 ...
随机推荐
- Python全栈开发之路 【第十九篇】:Bootstrap
一.下载和基本使用 官方地址:www.bootcss.com 二.响应式介绍 1.@meida 媒体查询 (1)响应式页面 为了页面能够适应不同工具的屏幕大小的限制,而开发的一种自适应页面,即 一次开 ...
- Python-类的特性(property)
什么是特性property property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值 例一:BMI指数(bmi是计算而来的,但很明显它听起来像是一个属性而非方法,如果我们将其做成一个 ...
- 【评分】Beta 答辩总结
[评分]Beta 答辩总结 总结 按时交 - 有分 晚交 - 0分 迟交一周以上 - 倒扣本次作业分数 抄袭 - 倒扣本次作业分数 由于前期不够重视,到beta评分才发现有5组的代码提交仅由一人&qu ...
- Python之加密模块
hashlib模块 加密方式以md5方式加密举例 是标准模块,直接导入即可 还有其他的加密方式,比如:.sha1()..sha224()..sha256()等,加密后的字符串长度更长,安全性更高 一. ...
- #Leetcode# 942. DI String Match
https://leetcode.com/problems/di-string-match/ Given a string S that only contains "I" (in ...
- 小程序wepy.js框架总结
wepy.js借鉴了Vue的语法风格和功能特性,对官方提供的框架进行了封装,更贴近于MVVM架构模式,让开发者更加容易上手,增加开发效率.(脏数据处理--是否有标识.是否有响应) 前端开发的对组件化开 ...
- js 通过url获取里面的参数值
场景描述:当我们从一个页面要带有一两个值跳转到另一个页面,另一个页面要使用这些参数的时候,我们就需要通过js获取这些参数啦. 先贴上代码: function getQueryString(name) ...
- React Native之通知栏消息提示(android)
React Native之通知栏消息提示(android) 一,需求分析与概述 1.1,推送作为手机应用的基本功能,是手机应用的重要部分,如果自己实现一套推送系统费时费力,所以大部分的应用都会选择使用 ...
- 5 Http请求中文乱码处理
java 乱码分很多种,这里主要研究解决http请求中出现乱码的情况. http请求出现中文乱码的主要原因:发送方与接收方编码不一致,服务器默认支持的编码与web应用不一致,如:tomcat 是国外程 ...
- POJ1108_Split Windows 解题报告
Split Windows 题目链接:http://poj.org/problem?id=1108 题目大意: 给你一棵二叉树的先序遍历,有三种字符:|.-.A~Z,然后用窗口表示出来,|: 表示将当 ...