Description

Link.

Given is a tree. Every node initially has a color which is different from others'. (called \(col_{x}\))

Def: \(\text{dis}(x,y)\): the number of different colors on the simple path between x and y.

Supporting the following operations:

  1. RELEASE x: For each \(y\) on \(\text{path}(x,rt)\), make \(col_{y}\)=a new color which doesn't exist before.
  2. RECENTER x: Make \(x\) become the new root after running RELEASE x.
  3. REQUEST x: Print: for each \(y\) in \(\text{subtree}(x)\), the sum of \(\text{dis}(y,rt)\) divided the number of nodes in \(\text{subtree}(x)\).

Solution

Link Cut Tree.

We can know that \(\text{dis}(x,rt)\) is the number of Fake Edges on \(\text{path}(x,rt)\) pluses one.

If we change a Real Edge \((u,v)\), where \(dep_{u}<dep_{v}\) into a Fake Edge, for each node \(x\) in \(\text{subtree}(v)\), \(\text{dis}(x,rt)\) will be decreased by \(1\).

Vice versa.

In order to support such operation: decrease the subtree by \(1\), we can fix the DFS order of the given tree.

However, we also need to change the root. How can we fix the DFS order of the given tree?

Let's have a discussion. Denote \(x\) for the current operating node, \(rt\) for the current root.

  1. if \(rt=x\): modify the whole tree directly.
  2. if \(rt\) isn't in \(\text{subtree}(x)\): modify \(\text{subtree}(x)\).
  3. if \(rt\) is in \(\text{subtree}(x)\): modify \(\text{subtree}(x)\) and cancel the modfication of \(\text{subtree}(rt)\)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
vector<int> e[100010];
int n,m,indfn[100010],outdfn[100010],sjc,fa[100010][20],dep[100010],rtnow=1;
#define check(x,f) ((indfn[x]<indfn[f])|(indfn[x]>outdfn[f])) // check whether x isn't in subtree(f)
void dfs(int x,int las)
{
dep[x]=dep[las]+1,fa[x][0]=las,indfn[x]=++sjc;
for(int i=1;i^20;++i) fa[x][i]=fa[fa[x][i-1]][i-1];
for(unsigned int i=0;i<e[x].size();++i) if(e[x][i]^las) dfs(e[x][i],x);
outdfn[x]=sjc;
}
int getkth(int x,int k)
{
if(k==0) return x;
else
{
for(int i=0;i^20;++i) if((k>>i)&1) x=fa[x][i];
return x;
}
}
struct LinearTree
{
struct node
{
LL val,tag;
}nodes[400010];
void turn(int x,int l,int r)
{
if(nodes[x].tag)
{
int mid=(l+r)>>1;
nodes[x<<1].val+=(mid-l+1)*nodes[x].tag;
nodes[x<<1|1].val+=(r-mid)*nodes[x].tag;
nodes[x<<1].tag+=nodes[x].tag;
nodes[x<<1|1].tag+=nodes[x].tag;
nodes[x].tag=0;
}
}
void ins(int l,int r,int x,int fr,int ba,int val)
{
if(fr>ba||l>ba||r<fr) return;
if(l>=fr&&r<=ba) nodes[x].val+=(r-l+1)*val,nodes[x].tag+=val;
else
{
int mid=(l+r)>>1;
turn(x,l,r);
ins(l,mid,x<<1,fr,ba,val);
ins(mid+1,r,x<<1|1,fr,ba,val);
nodes[x].val=nodes[x<<1].val+nodes[x<<1|1].val;
}
}
LL find(int l,int r,int x,int fr,int ba)
{
if(fr>ba||l>ba||r<fr) return 0;
if(l>=fr&&r<=ba) return nodes[x].val;
else
{
int mid=(l+r)>>1;
turn(x,l,r);
return find(l,mid,x<<1,fr,ba)+find(mid+1,r,x<<1|1,fr,ba);
}
}
void modify(int x,LL val)
{
if(rtnow==x) ins(1,n,1,1,n,val);
else if(check(rtnow,x)) ins(1,n,1,indfn[x],outdfn[x],val);
else
{
int tmp=getkth(rtnow,dep[rtnow]-dep[x]-1);
ins(1,n,1,1,indfn[tmp]-1,val);
ins(1,n,1,outdfn[tmp]+1,n,val);
}
}
}lrt;
struct LinkCutTree
{
#define wis(x) (nodes[nodes[x].fa].ch[1]==(x))
#define isrt(x) ((nodes[nodes[x].fa].ch[0]^(x))&&(nodes[nodes[x].fa].ch[1]^(x)))
struct node
{
int ch[2],fa;
bool rev;
}nodes[100010];
void turn_down(int x)
{
if(nodes[x].rev)
{
swap(nodes[x].ch[0],nodes[x].ch[1]);
if(nodes[x].ch[0]) nodes[nodes[x].ch[0]].rev^=1;
if(nodes[x].ch[1]) nodes[nodes[x].ch[1]].rev^=1;
nodes[x].rev=0;
}
}
void turn_whole(int x)
{
if(!isrt(x)) turn_whole(nodes[x].fa);
turn_down(x);
}
void rotate(int x)
{
int f=nodes[x].fa,ff=nodes[f].fa,t=wis(x);
nodes[x].fa=ff;
if(!isrt(f)) nodes[ff].ch[wis(f)]=x;
nodes[f].ch[t]=nodes[x].ch[t^1];
nodes[nodes[x].ch[t^1]].fa=f;
nodes[x].ch[t^1]=f;
nodes[f].fa=x;
}
void splay(int x)
{
turn_whole(x);
while(!isrt(x))
{
int f=nodes[x].fa;
if(!isrt(f)) rotate((wis(x)^wis(f))?x:f);
rotate(x);
}
}
int findleft(int x)
{
turn_down(x);
while(nodes[x].ch[0]) x=nodes[x].ch[0],turn_down(x);
return x;
}
void access(int x)
{
for(int y=0;x;y=x,x=nodes[x].fa)
{
splay(x);
if(nodes[x].ch[1]) lrt.modify(findleft(nodes[x].ch[1]),1);
if(y) lrt.modify(findleft(y),-1);
nodes[x].ch[1]=y;
}
}
void makert(int x){access(x),splay(x),nodes[x].rev^=1;}
}lct;
char opt[20];
int opx;
template<typename T>
void read(T &hhh)
{
T x=0,f=1;
char c=getchar();
while(c<'0'||c>'9')
{
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^'0'),c=getchar();
if(~f) hhh=x;
else hhh=-x;
}
int main()
{
read(n),read(m);
for(int i=1,x,y;i<n;++i)
{
read(x),read(y);
e[x].emplace_back(y);
e[y].emplace_back(x);
}
dfs(1,0);
for(int i=1;i<=n;++i) lrt.ins(1,n,1,indfn[i],indfn[i],dep[i]),lct.nodes[i].fa=fa[i][0];
while(m--)
{
scanf("%s",opt),read(opx);
if(strcmp(opt,"RELEASE")==0) lct.access(opx);
else if(strcmp(opt,"RECENTER")==0) lct.makert(opx),rtnow=opx;
else
{
if(rtnow==opx) printf("%.10f\n",double(lrt.find(1,n,1,1,n))/n);
else if(check(rtnow,opx)) printf("%.10f\n",double(lrt.find(1,n,1,indfn[opx],outdfn[opx]))/(outdfn[opx]-indfn[opx]+1));
else
{
int tmp=getkth(rtnow,dep[rtnow]-dep[opx]-1);
printf("%.10f\n",double(lrt.find(1,n,1,1,indfn[tmp]-1)+lrt.find(1,n,1,outdfn[tmp]+1,n))/(indfn[tmp]+n-outdfn[tmp]-1));
}
}
}
return 0;
}

Solution -「BZOJ 3779」重组病毒的更多相关文章

  1. 【bzoj 3779】重组病毒

    Description 黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒.这种病毒的繁殖和变异能力极强.为了阻止这种病毒传播,某安全机构策划了一次实验,来研究这种病毒. ...

  2. Solution -「BZOJ 3812」主旋律

    \(\mathcal{Description}\)   Link.   给定含 \(n\) 个点 \(m\) 条边的简单有向图 \(G=(V,E)\),求 \(H=(V,E'\subseteq E)\ ...

  3. Solution -「BZOJ #3786」星系探索

    \(\mathcal{Description}\)   Link.   给定一棵含 \(n\) 个点的有根树,点有点权,支持 \(q\) 次操作: 询问 \(u\) 到根的点权和: 修改 \(u\) ...

  4. Solution -「BZOJ 4316」小C的独立集

    \(\mathcal{Description}\)   Link.   求包含 \(n\) 个结点 \(m\) 条边的仙人掌的最大独立集.   \(n\le5\times10^4\),\(m\le6\ ...

  5. Solution -「BZOJ 3331」压力

    \(\mathcal{Description}\)   Link.   给定一个 \(n\) 个点 \(m\) 条边的连通无向图,并给出 \(q\) 个点对 \((u,v)\),令 \(u\) 到 \ ...

  6. 「BZOJ 4228」Tibbar的后花园

    「BZOJ 4228」Tibbar的后花园 Please contact lydsy2012@163.com! 警告 解题思路 可以证明最终的图中所有点的度数都 \(< 3\) ,且不存在环长是 ...

  7. 「BZOJ 3645」小朋友与二叉树

    「BZOJ 3645」小朋友与二叉树 解题思路 令 \(G(x)\) 为关于可选大小集合的生成函数,即 \[ G(x)=\sum[i\in c ] x^i \] 令 \(F(x)\) 第 \(n\) ...

  8. 「BZOJ 4502」串

    「BZOJ 4502」串 题目描述 兔子们在玩字符串的游戏.首先,它们拿出了一个字符串集合 \(S\),然后它们定义一个字符串为"好"的,当且仅当它可以被分成非空的两段,其中每一段 ...

  9. 「BZOJ 4289」 PA2012 Tax

    「BZOJ 4289」 PA2012 Tax 题目描述 给出一个 \(N\) 个点 \(M\) 条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点 \(1\) 到点 \( ...

  10. 「BZOJ 2534」 L - gap字符串

    「BZOJ 2534」 L - gap字符串 题目描述 有一种形如 \(uv u\) 形式的字符串,其中 \(u\) 是非空字符串,且 \(v\) 的长度正好为 \(L\), 那么称这个字符串为 \( ...

随机推荐

  1. 洛谷 P7579 「RdOI R2」称重(weigh) 题解

    题意: 题目 一道交互题. 有 n 个球,里面有两个假球,假球比普通球的要轻,每次可以询问任意两组球的轻重关系,第一组轻为 < ,第二组轻为 > ,一样重量为 = . 思路: 先考虑在一个 ...

  2. Linq的所有用法(简单化)

    Linq 是一种强大的查询语言,可以过滤.排序和组合各种数据源.下面我们将讨论 Linq 的各种用法. Linq 的基本语法: Linq 可以应用于任何对象集合,以下是一个示例: var number ...

  3. 用R语言实现并行计算:基于R的数据处理和分析工具

    目录 引言 随着数据量的爆炸式增长,数据处理和分析的需求也越来越大.传统的批处理计算已经无法满足高效的数据处理和分析需求,因此,并行计算成为了一个重要的技术方向.然而,R语言作为一种开源.可视化能力强 ...

  4. NetBeans连接SQLServer2008配置

    一.配置SQL Server (一)SQL Server配置管理器 1.打开SQL Server配置管理器 (1)文件路径,我的是C:\Windows\SysWOW64\mmc.exe, 也可以从开始 ...

  5. 2023-07-06:RabbitMQ中的AMQP是什么?

    2023-07-06:RabbitMQ中的AMQP是什么? 答案2023-07-06: AMQP AMQP(Advanced Message Queuing Protocol)是一个应用层协议的开放标 ...

  6. Java相关小知识_6_15

    实体完整性要求每个表都有唯一标识符,每一个表中的主键字段不能为空或者重复的值. 参照完整性要求关系中不允许引用不存在的实体.设定相应的更新删除插入规则来更新参考表. Java语言使用的是Unicode ...

  7. 2023-07-16:讲一讲Kafka与RocketMQ中零拷贝技术的运用?

    2023-07-16:讲一讲Kafka与RocketMQ中零拷贝技术的运用? 答案2023-07-16: 什么是零拷贝? 零拷贝(英语: Zero-copy) 技术是指计算机执行操作时,CPU不需要先 ...

  8. Git 环境配置(详解版)

    前言 Git下载官网:https://git-scm.com/downloads 本次使用Github为配置前提(Gitee步骤类似) 环境搭建 1.git安装好去GitHub上注册一个账号,注册好后 ...

  9. 如何编写难以维护的React代码?——滥用useEffect

    如何编写难以维护的React代码?--滥用useEffect 在许多项目中,我们经常会遇到一些难以维护的React代码.其中一种常见的情况是滥用useEffect钩子,特别是在处理衍生状态时.让我们来 ...

  10. 2021-7-6 vue和axios使用get请求api实例

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <script sr ...