[BZOJ3779]重组病毒(LCT+DFS序线段树)
同[BZOJ4817]树点涂色,只是多了换根操作,分类讨论下即可。
#include<cstdio>
#include<algorithm>
#define lc ch[x][0]
#define rc ch[x][1]
#define ls (x<<1)
#define rs (ls|1)
#define lson ls,L,mid
#define rson rs,mid+1,R
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
#define For(i,x) for (int i=h[x],k; i; i=nxt[i])
typedef long long ll;
using namespace std; const int N=;
char op[];
ll tag[N<<],sm[N<<];
int n,m,u,v,x,rt,cnt,tim,rev[N],h[N],nxt[N<<],to[N<<];
int L[N],R[N],dep[N],fa[N][],ch[N][],sz[N],f[N];
void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; } inline int rd(){
int x=; char ch=getchar(); bool f=;
while (ch<'' || ch>'') f|=ch=='-',ch=getchar();
while (ch>='' && ch<='') x=(x<<)+(x<<)+(ch^),ch=getchar();
return f ? -x : x;
} int jump(int x,int k){
for (int i=; ~i; i--) if (k&(<<i)) x=fa[x][i]; return x;
} void push(int x,int L,int R){
if (!tag[x]) return;
int mid=(L+R)>>;
sm[ls]+=tag[x]*(mid-L+); tag[ls]+=tag[x];
sm[rs]+=tag[x]*(R-mid); tag[rs]+=tag[x];
tag[x]=;
} void mdf(int x,int L,int R,int l,int r,int k){
if (L==l && r==R){ sm[x]+=1ll*k*(R-L+); tag[x]+=k; return; }
int mid=(L+R)>>; push(x,L,R);
if (r<=mid) mdf(lson,l,r,k);
else if (l>mid) mdf(rson,l,r,k);
else mdf(lson,l,mid,k),mdf(rson,mid+,r,k);
sm[x]=sm[ls]+sm[rs];
} ll que(int x,int L,int R,int l,int r){
if (L==l && r==R) return sm[x];
int mid=(L+R)>>; push(x,L,R);
if (r<=mid) return que(lson,l,r);
else if (l>mid) return que(rson,l,r);
else return que(lson,l,mid)+que(rson,mid+,r);
} void dfs(int x){
L[x]=++tim; dep[x]=dep[fa[x][]]+; sz[x]=;
rep(i,,) fa[x][i]=fa[fa[x][i-]][i-];
mdf(,,n,L[x],L[x],dep[x]);
For(i,x) if ((k=to[i])!=fa[x][]) fa[k][]=x,f[k]=x,dfs(k),sz[x]+=sz[k];
R[x]=tim;
} bool isrt(int x){ return (!f[x]) || (ch[f[x]][]!=x && ch[f[x]][]!=x); }
void put(int x){ swap(lc,rc); rev[x]^=; }
void push(int x){ if (rev[x]) put(lc),put(rc),rev[x]=; }
void pd(int x){ if (!isrt(x)) pd(f[x]); push(x); } void rot(int x){
int y=f[x],z=f[y],w=ch[y][]==x;
if (!isrt(y)) ch[z][ch[z][]==y]=x;
f[x]=z; f[y]=x; f[ch[x][w^]]=y;
ch[y][w]=ch[x][w^]; ch[x][w^]=y;
} void splay(int x){
pd(x);
while (!isrt(x)){
int y=f[x],z=f[y];
if (!isrt(y)) (ch[z][]==y)^(ch[y][]==x) ? rot(x) : rot(y);
rot(x);
}
} void work(int x,int k){
if (rt==x) mdf(,,n,,n,k);
else if (L[rt]>=L[x] && L[rt]<=R[x]){
int t=jump(rt,dep[rt]-dep[x]-);
if (L[t]>) mdf(,,n,,L[t]-,k);
if (R[t]<n) mdf(,,n,R[t]+,n,k);
}else mdf(,,n,L[x],R[x],k);
} int find(int x){
push(x);
while (lc) x=lc,push(x);
return x;
} void access(int x){
for (int y=; x; y=x,x=f[x]){
splay(x);
if (rc) work(find(rc),);
if (y) work(find(y),-);
rc=y;
}
} void mkrt(int x){ access(x); splay(x); put(x); } int main(){
freopen("bzoj3779.in","r",stdin);
freopen("bzoj3779.out","w",stdout);
n=rd(); m=rd();
rep(i,,n) u=rd(),v=rd(),add(u,v),add(v,u);
dfs(); rt=;
while (m--){
scanf("%s",op); x=rd();
if (op[]=='L') access(x);
if (op[]=='C') mkrt(x),rt=x;
if (op[]=='Q'){
if (rt==x) printf("%.10lf\n",.*que(,,n,,n)/n);
else if (L[rt]>=L[x] && L[rt]<=R[x]){
int t=jump(rt,dep[rt]-dep[x]-);
ll res1=L[t]> ? que(,,n,,L[t]-) : ;
ll res2=R[t]<n ? que(,,n,R[t]+,n) : ;
printf("%.10lf\n",.*(res1+res2)/(n-sz[t]));
}else printf("%.10lf\n",.*que(,,n,L[x],R[x])/sz[x]);
}
}
return ;
}
[BZOJ3779]重组病毒(LCT+DFS序线段树)的更多相关文章
- 【BZOJ3779】重组病毒 LCT+DFS序
[BZOJ3779]重组病毒 Description 黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒.这种病毒的繁殖和变异能力极强.为了阻止这种病毒传播,某安全机构策 ...
- bzoj4817/luogu3703 树点涂色 (LCT+dfs序+线段树)
我们发现,这个染色的操作他就很像LCT中access的操作(为什么??),然后就自然而然地想到,其实一个某条路径上的颜色数量,就是我们做一个只有access操作的LCT,这条路径经过的splay的数量 ...
- BZOJ.4817.[SDOI2017]树点涂色(LCT DFS序 线段树)
题目链接 操作\(1.2\)裸树剖,但是操作\(3\)每个点的答案\(val\)很不好维护.. 如果我们把同种颜色的点划分到同一连通块中,那么向根染色的过程就是Access()! 最初所有点间都是虚边 ...
- [BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)
4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 692 Solved: 408[Submit][Status ...
- [BZOJ3779]重组病毒:Link-Cut Tree+线段树
分析 其实其他的题解说的都很清楚了. 一个点出发感染到根结点所花费的时间是路径上虚边的条数+1. RELEASE相当于\(access()\). RECENTER相当于\(makeroot()\).( ...
- Educational Codeforces Round 6 E dfs序+线段树
题意:给出一颗有根树的构造和一开始每个点的颜色 有两种操作 1 : 给定点的子树群体涂色 2 : 求给定点的子树中有多少种颜色 比较容易想到dfs序+线段树去做 dfs序是很久以前看的bilibili ...
- 【BZOJ-3252】攻略 DFS序 + 线段树 + 贪心
3252: 攻略 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 339 Solved: 130[Submit][Status][Discuss] D ...
- Codeforces 343D Water Tree(DFS序 + 线段树)
题目大概说给一棵树,进行以下3个操作:把某结点为根的子树中各个结点值设为1.把某结点以及其各个祖先值设为0.询问某结点的值. 对于第一个操作就是经典的DFS序+线段树了.而对于第二个操作,考虑再维护一 ...
- BZOJ2434 [Noi2011]阿狸的打字机(AC自动机 + fail树 + DFS序 + 线段树)
题目这么说的: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母.经阿狸研究发现,这个打字机是这样工作的: 输入小 ...
随机推荐
- MeasureSpec介绍及使用详解
一个MeasureSpec封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求.一个MeasureSpec有大小和模式组成.他有三种模式: UNSPECIFIED ...
- shell脚本练习题->1
猜随机数的大小 描述: 写一个猜数字脚本,当用户输入的数字和预设数字(随机生成一个0-100的数字)一样时,直接退出,否则让用户一直输入:并且提示用户输入的数字比预设数字大或者小 分析: 1:随机数字 ...
- js中字符串的常用方法
一.普通方法 1.字符方法 动态方法:1.str.charAt(index); 返回子字符串,index为字符串下标,index取值范围[0,str.length-1] 动态方法:2.str.cha ...
- java基础74 XML解析中的SAX解析相关知识点(网页知识)
1.SAX解析工具 SAX解析工具:是Sun公司提供的,内置JDK中.org.xml.sax.* 点击查看: DOM解析相关知识:以及DOM和SAX解析的原理(区别) 2.SAX解析的 ...
- java基础49 IO流技术(对象输入流/对象输出流)
1.对象输入输出流 对象注意作用是用于写对象信息与读取对象信息 1.对象输出流:ObjectOutputStream 2.对象输入流:ObjectInputStream 2.对象输入输出流的步骤 ...
- putIfAbsent
public static HashSet<Long> getOrInitHashMapCacheValue(Long mId){ // HashSet<Long> set = ...
- 能ping但是无法上网
管理员权限,执行以下这个命令就好了. netsh winsock reset 配置问题,重置windows socket.
- Master和worker模式
让和hadoop的设计思想是一样的,Master负责分配任务和获取任务的结果,worker是真正处理业务逻辑的. 使用ConcurrentLikedQueue去承载所有的任务,因为会有多个worker ...
- MP3 Fuzz学习
这篇文章主要是学习一波MP3格式fuzz的知识.目录如下 0x0.MP3格式的构成 0x0.MP3格式的构成 MP3是一种通俗叫法,学名叫MPEG1 Layer-3.MP3是三段式的结构,依次由ID3 ...
- 8-16 不无聊序列 non-boring sequences uva1608
题意: 如果一个序列的任意连续子序列中至少有一个只出现一次的元素 则称这个序列是 不无聊序列 输入一个n个元素的序列a 判断是不是不无聊序列 一开始想当然 以为只要 2位的子序列都满足即可 ...