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\), 那么称这个字符串为 \( ...
随机推荐
- Weblogic反序列化(CVE-2023-21839)漏洞复现
前言 序列化(Serialization):将对象的状态信息转换为可以存储或传输的形式的过程,一般将对象转换为字节流.序列化时,对象的当前状态被写入到临时或持久性存储区(文件.内存.数据库等). 反序 ...
- pip 20.3 新版本发布!即将抛弃 Python 2.x
据 Python 软件基金会消息,Python Packaging Authority 和 pip 团队于北美时间11月30日宣布发布 pip 20.3版本,开发者可以通过运行 python -m p ...
- 从 0 到 1 搭建自己的脚手架(java 后端)
一.脚手架是什么 脚手架是一种基础设施工具,用于快速生成项目的框架代码和文件结构.它是一种标准化的开发工具,使开发人员能够在项目的早期阶段快速搭建出一个具备基本功能和结构的系统. 二.脚手架的意义 主 ...
- 逍遥自在学C语言 | 宏定义技巧让你的C代码快人一步
前言 在C语言中,宏定义是一种预处理指令,用于在代码中定义和使用常量.函数或代码片段的替代. 宏定义使用#define关键字来定义,并在代码中进行替换.宏定义具有以下优点: 简化代码:宏定义可以将一些 ...
- CentOS7 本地光盘镜像rpm包
CentOS7 本地光盘镜像rpm包 一.前言 rpm包的下载方式 通过本地光盘镜像下载rpm,centos7.iso镜像文件,内置了绝大多数软件的rpm包(本文章即演示如何配置本地rpm) 在线下载 ...
- 洛谷 P8179 Tyres
滴叉题/se/se 题意 直接复制了 有 \(n\) 套轮胎,滴叉需要用这些轮胎跑 \(m\) 圈.使用第 \(i\) 套轮胎跑的第 \(j\) 圈(对每套轮胎单独计数)需要 \(a_i+b_i(j- ...
- docker-compose单服务器部署ELK
docker-compose 部署ELK 本项目采用的ELK版本为6.5.3,7.0+ 以上的版本部分配置不适合,请查看docker-compose多服务器部署ELK文章 目录结构 elk |--do ...
- idea设置退出软件提示
进入设置
- React后台管理系统10 菜单数据的整理、以及其余路径的配置、刷新时默认当前选中样式
对菜单进行数据整理 import { DesktopOutlined, FileOutlined, PieChartOutlined, TeamOutlined, UserOutlined, } fr ...
- P3134 [USACO16JAN] Lights Out G 关灯
P3134 [USACO16JAN] Lights Out G 关灯 目录 P3134 [USACO16JAN] Lights Out G 关灯 [USACO16JAN] Lights Out G 题 ...