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\), 那么称这个字符串为 \( ...
随机推荐
- 测序数据学习笔记:bcl2fastq 安装
相比二进制的 bcl2fastq2,基于 Perl 语言的 bcl2fastq-1.8.4 或许是从源码层面学习了解 Illumina 测序数据处理一个不错的选择.源码版本的 bcl2fastq-1. ...
- 【Python&目标识别】labelimg报错IndexError: list index out of range
博主在使用labelimg选取深度学习样本时,命令行报错IndexError: list index out of range,几经周折终于解决了,所以跟大家分享一下. ...
- 体验昇腾Ascend C 编程语言极简易用的算子开发
摘要:昇腾Ascend C编程语言,让基于昇腾AI的算法创新更加简单. 本文分享自华为云社区<CANN黑科技解密|昇腾Ascend C编程语言 - 极简易用的算子开发体验>,作者:昇腾CA ...
- GO通道:无缓冲通道与缓冲通道
转载请注明出处: 1.通道定义 在多个协程之间进行通信和管理,可以使用 Go 语言提供的通道(Channel)类型.通道是一种特殊的数据结构,可以在协程之间进行传递数据,从而实现协程之间的通信和同步. ...
- 这问题巧了,SpringMVC 不同参数处理机制引发的思考
这个问题非常有趣,不是SpringMVC 的问题,是实际开发中混合使用了两种请求方式暴露出来的. 问题场景 功能模块中,提供两个 Http 服务.一个是列表查询(application/json 请求 ...
- 看懂java序列化,这篇就够了
前言 相信大家日常开发中,经常看到 Java 对象 "implements Serializable".那么,它到底有什么用呢?本文带你全方位的解读序列化与反序列化这一块知识点. ...
- 前台vue发送json格式,后台srpeingboot不能自动处理解决办法
使用HashMap解决,如下图
- 【Docker】部署Redis
1.下载镜像 #下载最新版Redis镜像 (其实此命令就等同于 : docker pull redis:latest ) docker pull redis # 下载指定版本的Redis镜像 (xxx ...
- 即构✖叮咚课堂:行业第一套AI课堂解决方案是怎么被实现的?
AI走进教育,是传统教育的一次迭代进化 在教育问题上,我们看到两类话题最容易引发公众讨论:教育公平和个性化教育,"互联网+教育"有可能解决第一类话题,"AI教育" ...
- centOS7 磁盘扩容(2T以上)
centOS7 磁盘扩容 1.安装parted分区工具 yum install -y parted 2.查看服务器分区情况 #fdisk -l 或者 lsblk 找到新增磁盘名称 例如/dev/sdb ...