Solution -「BZOJ 3779」重组病毒
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:
RELEASE x: For each \(y\) on \(\text{path}(x,rt)\), make \(col_{y}\)=a new color which doesn't exist before.RECENTER x: Make \(x\) become the new root after runningRELEASE x.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.
- if \(rt=x\): modify the whole tree directly.
- if \(rt\) isn't in \(\text{subtree}(x)\): modify \(\text{subtree}(x)\).
- 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」重组病毒的更多相关文章
- 【bzoj 3779】重组病毒
Description 黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒.这种病毒的繁殖和变异能力极强.为了阻止这种病毒传播,某安全机构策划了一次实验,来研究这种病毒. ...
- Solution -「BZOJ 3812」主旋律
\(\mathcal{Description}\) Link. 给定含 \(n\) 个点 \(m\) 条边的简单有向图 \(G=(V,E)\),求 \(H=(V,E'\subseteq E)\ ...
- Solution -「BZOJ #3786」星系探索
\(\mathcal{Description}\) Link. 给定一棵含 \(n\) 个点的有根树,点有点权,支持 \(q\) 次操作: 询问 \(u\) 到根的点权和: 修改 \(u\) ...
- Solution -「BZOJ 4316」小C的独立集
\(\mathcal{Description}\) Link. 求包含 \(n\) 个结点 \(m\) 条边的仙人掌的最大独立集. \(n\le5\times10^4\),\(m\le6\ ...
- Solution -「BZOJ 3331」压力
\(\mathcal{Description}\) Link. 给定一个 \(n\) 个点 \(m\) 条边的连通无向图,并给出 \(q\) 个点对 \((u,v)\),令 \(u\) 到 \ ...
- 「BZOJ 4228」Tibbar的后花园
「BZOJ 4228」Tibbar的后花园 Please contact lydsy2012@163.com! 警告 解题思路 可以证明最终的图中所有点的度数都 \(< 3\) ,且不存在环长是 ...
- 「BZOJ 3645」小朋友与二叉树
「BZOJ 3645」小朋友与二叉树 解题思路 令 \(G(x)\) 为关于可选大小集合的生成函数,即 \[ G(x)=\sum[i\in c ] x^i \] 令 \(F(x)\) 第 \(n\) ...
- 「BZOJ 4502」串
「BZOJ 4502」串 题目描述 兔子们在玩字符串的游戏.首先,它们拿出了一个字符串集合 \(S\),然后它们定义一个字符串为"好"的,当且仅当它可以被分成非空的两段,其中每一段 ...
- 「BZOJ 4289」 PA2012 Tax
「BZOJ 4289」 PA2012 Tax 题目描述 给出一个 \(N\) 个点 \(M\) 条边的无向图,经过一个点的代价是进入和离开这个点的两条边的边权的较大值,求从起点 \(1\) 到点 \( ...
- 「BZOJ 2534」 L - gap字符串
「BZOJ 2534」 L - gap字符串 题目描述 有一种形如 \(uv u\) 形式的字符串,其中 \(u\) 是非空字符串,且 \(v\) 的长度正好为 \(L\), 那么称这个字符串为 \( ...
随机推荐
- chess草稿(附代码!)
2022/8/12日过了,代码如下:(已删除调试语句,保留注释,为了使代码更容易看懂并没有卡常.卡完常的代码不是给人看的) 点击查看代码 /* 倒序操作+合并连通块+维护集合,支持合并.区间查询+线段 ...
- JS基础语法(一)
javascript简介 javascrpit是是一种轻量级的编程语言,常用于web前端开发.另外js还可以用来写node.js类型的服务和工具,在测试web项目的时候需要了解. 变量 js定义变量有 ...
- NameError: name 'List' is not defined
当在python出现该问题是,使用from typing import List.
- 也谈Python编码格式
python在升级到Python3之后,因为Utf-8作为没有歧义的统一标准编码,相信很少人再会碰到编码格式的问题,但现实总会不停地打脸理想,告诉我们Too Young Too Simple.先不扯闲 ...
- 【LeetCode摩尔投票】有趣的简单题:数组中出现次数超过一半的数字
数组中出现次数超过一半的数字 https://leetcode.cn/problems/shu-zu-zhong-chu-xian-ci-shu-chao-guo-yi-ban-de-shu-zi-l ...
- C#使用企业微信群机器人推送生产数据
在日常的工作生产中,经常会有将将生产数据或者一些信息主动推送给相关的管理人员,我们公司在开发WMS系统时,为了仓库的储存安全,需要在危废品库存达到一定的储量时,自动通知仓管员去处理危废品,所以就需要程 ...
- Python运维开发之路《python基础介绍》
一. python介绍相关 1. Python简介 Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. - Python 的设计具有很强的可读性,相比其他语言经常使用英文关 ...
- Visual Studio Code调试和发布ASP.NET Core Web应用
前言 上一篇文章主要讲了Visual Studio Code安装C#开发工具包并编写ASP.NET Core Web应用有兴趣的同学可以去看看,今天咱们主要是要讲讲如何在VS Code中调试和发布AS ...
- Flutter ListView 不满屏 无法滚动
场景: flutter ListView 在做上拉加载的时候,未list添加controller后,数据不满屏,无法滚动 解决: 未listview 设置: physics: const Always ...
- NumPy(1)-常用的初始化方法
一.NumPy介绍 NumPy是Python中科学计算的基础包,它是一个Python库,提供多维数组对象,各种派生对象(如掩码数组和矩阵),以及用于数组快速操作的各种API,有包括数学.逻辑.形状操作 ...