一个点的感染时间为它到根路径上虚边数+1。

用Link-Cut Tree模拟虚实边切换,每次切换时等价于在一段或两段DFS序区间更新,线段树维护即可。

时间复杂度$O(n\log^2n)$。

#include<cstdio>
typedef long long ll;
const int N=100010,M=262145;
int n,m,i,x,y,root;
int g[N],nxt[N<<1],v[N<<1],ed;
int top[N],child[N],fa[N],d[N],size[N],st[N],en[N],dfn,seq[N];
inline void addedge(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
inline void swap(int&a,int&b){int c=a;a=b;b=c;}
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
int tag[M];ll val[M];
inline void add1(int x,int a,int b,int p){val[x]+=(ll)(b-a+1)*p;tag[x]+=p;}
inline void pb(int x,int a,int b){
if(tag[x]){
int mid=(a+b)>>1;
add1(x<<1,a,mid,tag[x]),add1(x<<1|1,mid+1,b,tag[x]),tag[x]=0;
}
}
inline void up(int x){val[x]=val[x<<1]+val[x<<1|1];}
void build(int x,int a,int b){
if(a==b){val[x]=seq[a];return;}
int mid=(a+b)>>1;
build(x<<1,a,mid),build(x<<1|1,mid+1,b),up(x);
}
void change(int x,int a,int b,int c,int d,int p){
if(c>d)return;
if(c<=a&&b<=d){add1(x,a,b,p);return;}
pb(x,a,b);
int mid=(a+b)>>1;
if(c<=mid)change(x<<1,a,mid,c,d,p);
if(d>mid)change(x<<1|1,mid+1,b,c,d,p);
up(x);
}
ll ask(int x,int a,int b,int c,int d){
if(c>d)return 0;
if(c<=a&&b<=d)return val[x];
pb(x,a,b);
int mid=(a+b)>>1;ll t=0;
if(c<=mid)t=ask(x<<1,a,mid,c,d);
if(d>mid)t+=ask(x<<1|1,mid+1,b,c,d);
return up(x),t;
}
inline int lca2(int x,int y){
int t;
while(top[x]!=top[y])t=top[x],x=fa[top[x]];
return x==y?t:child[y];
}
inline void subadd(int x,int p){
if(x==root){change(1,1,n,1,n,p);return;}
if(st[x]>st[root]||en[x]<en[root]){change(1,1,n,st[x],en[x],p);return;}
int y=lca2(root,x);
change(1,1,n,1,st[y]-1,p),change(1,1,n,en[y]+1,n,p);
}
inline double query(int x){
if(x==root)return(double)ask(1,1,n,1,n)/n;
if(st[x]>st[root]||en[x]<en[root])return(double)ask(1,1,n,st[x],en[x])/(en[x]-st[x]+1);
int y=lca2(root,x);
return(double)(ask(1,1,n,1,st[y]-1)+ask(1,1,n,en[y]+1,n))/(n-en[y]+st[y]-1);
}
int f[N],son[N][2],a[N];bool rev[N];
inline bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;}
inline void rev1(int x){if(!x)return;swap(son[x][0],son[x][1]);rev[x]^=1;}
inline void pb(int x){if(rev[x])rev1(son[x][0]),rev1(son[x][1]),rev[x]=0;}
inline void rotate(int x){
int y=f[x],w=son[y][1]==x;
son[y][w]=son[x][w^1];
if(son[x][w^1])f[son[x][w^1]]=y;
if(f[y]){
int z=f[y];
if(son[z][0]==y)son[z][0]=x;else if(son[z][1]==y)son[z][1]=x;
}
f[x]=f[y];son[x][w^1]=y;f[y]=x;
}
inline void splay(int x){
int s=1,i=x,y;a[1]=i;
while(!isroot(i))a[++s]=i=f[i];
while(s)pb(a[s--]);
while(!isroot(x)){
y=f[x];
if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
rotate(x);
}
}
inline int getson(int x){
pb(x);
while(son[x][0])pb(x=son[x][0]);
return x;
}
inline void access(int x){
for(int y=0;x;y=x,x=f[x]){
splay(x);
if(son[x][1])subadd(getson(son[x][1]),1);
if(y)subadd(getson(y),-1);
son[x][1]=y;
}
}
inline void makeroot(int x){access(x);splay(x);rev1(root=x);}
void dfs1(int x,int pre,int dep){
size[x]=1;d[x]=dep;fa[x]=f[x]=pre;
int heavy=0,sizemax=0,i;
for(i=g[x];i;i=nxt[i])if(v[i]!=pre){
dfs1(v[i],x,dep+1),size[x]+=size[v[i]];
if(size[v[i]]>sizemax)sizemax=size[v[i]],heavy=v[i];
}
if(heavy)child[x]=heavy;
}
void dfs2(int x,int pre,int t){
st[x]=++dfn;seq[dfn]=d[x];top[x]=t;
if(child[x])dfs2(child[x],x,t);
for(int i=g[x];i;i=nxt[i])if(v[i]!=pre&&v[i]!=child[x])dfs2(v[i],x,v[i]);
en[x]=dfn;
}
char op[10];
int main(){
read(n);read(m);
for(i=1;i<n;i++)read(x),read(y),addedge(x,y),addedge(y,x);
dfs1(root=1,0,1);dfs2(1,0,1);
build(1,1,n);
while(m--){
scanf("%s%d",op,&x);
if(op[2]=='L')access(x);
if(op[2]=='C')makeroot(x);
if(op[2]=='Q')printf("%.10f\n",query(x));
}
return 0;
}

  

BZOJ3779 : 重组病毒的更多相关文章

  1. BZOJ3779重组病毒LCT

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

  2. [BZOJ3779]重组病毒(LCT+DFS序线段树)

    同[BZOJ4817]树点涂色,只是多了换根操作,分类讨论下即可. #include<cstdio> #include<algorithm> #define lc ch[x][ ...

  3. bzoj千题计划274:bzoj3779: 重组病毒

    http://www.lydsy.com/JudgeOnline/problem.php?id=3779 有一棵树,初始每个节点有不同的颜色 操作1:根节点到x的路径上的点 染上一种没有出现过的颜色 ...

  4. bzoj3779: 重组病毒 link-cut-tree

    题目传送门 这道题看了做了个神转换.....推荐个博客给各位大爷看看吧神犇传送门 代码敲了半天....题目也读了半天 线段树维护的东西很容易和lct混在一起 调了调能过也是很开心啊 运气比较好吧233 ...

  5. [BZOJ3779]重组病毒:Link-Cut Tree+线段树

    分析 其实其他的题解说的都很清楚了. 一个点出发感染到根结点所花费的时间是路径上虚边的条数+1. RELEASE相当于\(access()\). RECENTER相当于\(makeroot()\).( ...

  6. 【BZOJ3779】重组病毒 LCT+DFS序

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

  7. 【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序

    3779: 重组病毒 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 224  Solved: 95[Submit][Status][Discuss] ...

  8. 【bzoj 3779】重组病毒

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

  9. BZOJ 3779 重组病毒 LCT+线段树(维护DFS序)

    原题干(由于是权限题我就直接砸出原题干了,要看题意概述的话在下面): Description 黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒.这种病毒的繁殖和变异能力 ...

随机推荐

  1. vue element-ui表格里时间戳转换成时间显示

    工作中遇到后台给的表格数据里时间是一个13位的时间戳,需要转换成时间显示在表格里, 可以用element-ui表格自带的:formatter函数,来格式化表格内容: // 时间戳转换成时间 // 使用 ...

  2. (64位)本体学习程序(ontoEnrich)系统使用说明文档

    系统运行:文件夹system下,可执行文件ontoEnrichment 概念学习 --------------------------------------------------------1.简 ...

  3. Python 入门基础6 --字符编码、文件操作1

    今日内容: 1.字符编码 2.字符与字节 3.文件操作 一.字符编码 了解: cpu:将数据渲染给用户 内存:临时存放数据,断电消失 硬盘:永久存放数据,断电后不消失 1.1 什么是编码? 人类能够识 ...

  4. KNN实现手写数字识别

    KNN实现手写数字识别 博客上显示这个没有Jupyter的好看,想看Jupyter Notebook的请戳KNN实现手写数字识别.ipynb 1 - 导入模块 import numpy as np i ...

  5. lucene修改索引——(六)

    原理: 修改的原理是先删除,后增加一个,这也是常用的一种修改的方式. 删除的文档的id不会被新增加的文档占用,类似于mysql的自增,当删除一个id=2时,以后id=2就是空着的,不会上来一个把2给占 ...

  6. python3之模块urllib

    urllib是python内置的HTTP请求库,无需安装即可使用,它包含了4个模块: request:它是最基本的http请求模块,用来模拟发送请求 error:异常处理模块,如果出现错误可以捕获这些 ...

  7. CentOS安装SVN客户端

    1.检查系统是否已经安装如果安装就卸载 rpm -qa subversion yum remove subversion 2.安装 yum install subversion 3.建立SVN库 mk ...

  8. python3 操作appium

    # -*- coding: utf-8 -*- # @Time : 2018/10/8 11:00 # @Author : cxa # @File : test.py # @Software: PyC ...

  9. 浅谈TCP拥塞控制算法

    TCP通过维护一个拥塞窗口来进行拥塞控制,拥塞控制的原则是,只要网络中没有出现拥塞,拥塞窗口的值就可以再增大一些,以便把更多的数据包发送出去,但只要网络出现拥塞,拥塞窗口的值就应该减小一些,以减少注入 ...

  10. C/C++的64位整型

    在C/C++中,64为整型一直是一种没有确定规范的数据类型.现今主流的编译器中,对64为整型的支持也是标准不一,形态各异.一般来说,64位整型的定义方式有long long和__int64两种(VC还 ...