Bzoj3779 重组病毒
Submit: 408 Solved: 163
[Submit][Status][Discuss]
Description
黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒。这种病毒的繁殖和变异能力极强。为了阻止这种病毒传播,某安全机构策划了一次实验,来研究这种病毒。
实验在一个封闭的局域网内进行。局域网内有n台计算机,编号为1~n。一些计算机之间通过网线直接相连,形成树形的结构。局域网中有一台特殊的计算机,称之为核心计算机。根据一些初步的研究,研究员们拟定了一个一共m步的实验。实验开始之前,核心计算机的编号为1,每台计算机中都有病毒的一个变种,而且每台计算机中的变种都不相同。实验中的每一步会是下面中的一种操作:
1、 RELEASE x
在编号为x的计算机中植入病毒的一个新变种。这个变种在植入之前不存在于局域网中。
2、 RECENTER x
将核心计算机改为编号为x的计算机。但是这个操作会导致原来核心计算机中的病毒产生新变种,并感染过来。换言之,假设操作前的核心计算机编号为y,相当于在操作后附加了一次RELEASE y的操作。
根据研究的结论,在植入一个新变种时,病毒会在局域网中搜索核心计算机的位置,并沿着网络中最短的路径感染过去。
而第一轮实验揭露了一个惊人的真相:病毒的不同变种是互斥的。新变种在感染一台已经被旧变种感染的电脑时,会把旧变种完全销毁之后再感染。但研究员发现了实现过程中的漏洞。如果新变种在感染过程中尚未销毁过这类旧变种,需要先花费1单位时间分析旧变种,才能销毁。如果之前销毁过这类旧变种,就可以认为销毁不花费时间。病毒在两台计算机之间的传播亦可认为不花费时间。
研究员对整个感染过程的耗时特别感兴趣,因为这是消灭病毒的最好时机。于是在m步实验之中,研究员有时还会做出如下的询问:
3、 REQUEST x
询问如果在编号为x的计算机的关键集合中的计算机中植入一个新变种,平均感染时间为多长。编号为y的计算机在编号为x的计算机的关键集合中,当且仅当从y沿网络中的最短路径感染到核心计算机必须经过x。由于有RECENTER操作的存在,这个集合并不一定是始终不变的。
至此,安全机构认为已经不需要实际的实验了,于是他们拜托你编写一个程序,模拟实验的结果,并回答所有的询问。
实验在一个封闭的局域网内进行。局域网内有n台计算机,编号为1~n。一些计算机之间通过网线直接相连,形成树形的结构。局域网中有一台特殊的计算机,称之为核心计算机。根据一些初步的研究,研究员们拟定了一个一共m步的实验。实验开始之前,核心计算机的编号为1,每台计算机中都有病毒的一个变种,而且每台计算机中的变种都不相同。实验中的每一步会是下面中的一种操作:
1、 RELEASE x
在编号为x的计算机中植入病毒的一个新变种。这个变种在植入之前不存在于局域网中。
2、 RECENTER x
将核心计算机改为编号为x的计算机。但是这个操作会导致原来核心计算机中的病毒产生新变种,并感染过来。换言之,假设操作前的核心计算机编号为y,相当于在操作后附加了一次RELEASE y的操作。
根据研究的结论,在植入一个新变种时,病毒会在局域网中搜索核心计算机的位置,并沿着网络中最短的路径感染过去。
而第一轮实验揭露了一个惊人的真相:病毒的不同变种是互斥的。新变种在感染一台已经被旧变种感染的电脑时,会把旧变种完全销毁之后再感染。但研究员发现了实现过程中的漏洞。如果新变种在感染过程中尚未销毁过这类旧变种,需要先花费1单位时间分析旧变种,才能销毁。如果之前销毁过这类旧变种,就可以认为销毁不花费时间。病毒在两台计算机之间的传播亦可认为不花费时间。
研究员对整个感染过程的耗时特别感兴趣,因为这是消灭病毒的最好时机。于是在m步实验之中,研究员有时还会做出如下的询问:
3、 REQUEST x
询问如果在编号为x的计算机的关键集合中的计算机中植入一个新变种,平均感染时间为多长。编号为y的计算机在编号为x的计算机的关键集合中,当且仅当从y沿网络中的最短路径感染到核心计算机必须经过x。由于有RECENTER操作的存在,这个集合并不一定是始终不变的。
至此,安全机构认为已经不需要实际的实验了,于是他们拜托你编写一个程序,模拟实验的结果,并回答所有的询问。
Input
输入的第一行包含两个整数n和m,分别代表局域网中计算机的数量,以及操作和询问的总数。
接下来n-1行,每行包含两个整数x和y,表示局域网中编号为x和y的计算机之间有网线直接相连。
接下来m行,每行包含一个操作或者询问,格式如问题描述中所述。
接下来n-1行,每行包含两个整数x和y,表示局域网中编号为x和y的计算机之间有网线直接相连。
接下来m行,每行包含一个操作或者询问,格式如问题描述中所述。
Output
对于每个询问,输出一个实数,代表平均感染时间。输出与答案的绝对误差不超过 10^(-6)时才会被视为正确。
Sample Input
8 6
1 2
1 3
2 8
3 4
3 5
3 6
4 7
REQUEST 7
RELEASE 3
REQUEST 3
RECENTER 5
RELEASE 2
REQUEST 1
1 2
1 3
2 8
3 4
3 5
3 6
4 7
REQUEST 7
RELEASE 3
REQUEST 3
RECENTER 5
RELEASE 2
REQUEST 1
Sample Output
4.0000000000
2.0000000000
1.3333333333
2.0000000000
1.3333333333
HINT
N < = 1 00 000 M < = 1 00 000
树 LCT+LCA+线段树 脑洞题
初始的时候,每个结点的权值就是它的深度。
观察发现每个结点的权值实际上就是它access的时候向上经过的虚边数量。
于是1操作就是access,路上把LCT结点的原右儿子所在子树权值全部+1,把新右儿子所在子树权值全部-1,这一过程可以用DFS序+线段树维护
2操作就是makeroot,自带一个access操作
3操作换根比较麻烦,实际上只需要记录当前根,每次仍在最初的树上操作,根据原根与现根的位置关系讨论即可。
↑比如说这种情况,要修改的就是除了nowroot所在子树区间以外的左右两段(图中没有左段)区间
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 #define LL long long 9 using namespace std; 10 const int mxn=100010; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 struct edge{ 18 int v,nxt; 19 }e[mxn<<1]; 20 int hd[mxn],mct=0; 21 void add_edge(int u,int v){ 22 e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return; 23 } 24 namespace TC{ 25 struct node{ 26 int fa,top,son; 27 int sz; 28 }t[mxn]; 29 int dep[mxn],ind[mxn],out[mxn],dtime; 30 int mp[mxn]; 31 void DFS(int u,int ff){ 32 dep[u]=dep[ff]+1; 33 t[u].sz++; 34 for(int i=hd[u],v;i;i=e[i].nxt){ 35 if(e[i].v==ff)continue; 36 v=e[i].v; 37 t[v].fa=u; 38 DFS(v,u); 39 t[u].sz+=t[v].sz; 40 if(t[v].sz>t[t[u].son].sz)t[u].son=v; 41 } 42 return; 43 } 44 void DFS2(int u,int top){ 45 ind[u]=++dtime; 46 mp[dtime]=u; 47 t[u].top=top; 48 if(t[u].son){ 49 DFS2(t[u].son,top); 50 for(int i=hd[u];i;i=e[i].nxt){ 51 if(e[i].v==t[u].son || e[i].v==t[u].fa)continue; 52 DFS2(e[i].v,e[i].v); 53 } 54 } 55 out[u]=dtime; 56 return; 57 } 58 int LCA(int x,int y){ 59 int last=0; 60 while(t[x].top!=t[y].top){ 61 if(dep[t[x].top]<dep[t[y].top])swap(x,y); 62 last=t[x].top; 63 x=t[t[x].top].fa; 64 } 65 if(x==y)return last; 66 else return t[y].son; 67 } 68 } 69 int n,m,nowroot; 70 struct SGT{ 71 #define lc rt<<1 72 #define rc rt<<1|1 73 struct node{ 74 LL smm,mk,mx; 75 }t[mxn<<2]; 76 void pushup(int rt){ 77 t[rt].smm=t[lc].smm+t[rc].smm; 78 return; 79 } 80 inline void PD(int l,int r,int rt){ 81 if(t[rt].mk){ 82 t[lc].mk+=t[rt].mk; 83 t[rc].mk+=t[rt].mk; 84 int mid=(l+r)>>1; 85 t[lc].smm+=t[rt].mk*(LL)(mid-l+1); 86 t[rc].smm+=t[rt].mk*(LL)(r-mid); 87 t[lc].mx+=t[rt].mk;t[rc].mx+=t[rt].mk; 88 t[rt].mk=0; 89 } 90 return; 91 } 92 void Build(int l,int r,int rt){ 93 if(l==r){ 94 t[rt].smm=t[rt].mx=TC::dep[TC::mp[l]]; return; 95 } 96 int mid=(l+r)>>1; 97 Build(l,mid,lc);Build(mid+1,r,rc); 98 pushup(rt); 99 return; 100 } 101 void update(int L,int R,int v,int l,int r,int rt){ 102 if(L>R)return; 103 if(L<=l && r<=R){ 104 t[rt].mk+=v; 105 t[rt].smm+=(LL)v*(LL)(r-l+1); 106 return; 107 } 108 PD(l,r,rt); 109 int mid=(l+r)>>1; 110 if(L<=mid)update(L,R,v,l,mid,lc); 111 if(R>mid)update(L,R,v,mid+1,r,rc); 112 pushup(rt); 113 return; 114 } 115 LL qsum(int L,int R,int l,int r,int rt){ 116 if(L>R)return 0; 117 if(L<=l && r<=R){return t[rt].smm;} 118 PD(l,r,rt); 119 LL res=0; 120 int mid=(l+r)>>1; 121 if(L<=mid)res+=qsum(L,R,l,mid,lc); 122 if(R>mid)res+=qsum(L,R,mid+1,r,rc); 123 pushup(rt); 124 return res; 125 } 126 void Q_UPD(int x,int v){ 127 using namespace TC; 128 int rt=nowroot; 129 if(rt==x)update(1,n,v,1,n,1); 130 else 131 if(ind[x]<ind[rt] && out[rt]<=out[x]){//两段区间 132 rt=LCA(rt,x); 133 update(1,ind[rt]-1,v,1,n,1); 134 update(out[rt]+1,n,v,1,n,1); 135 } 136 else update(ind[x],out[x],v,1,n,1); 137 } 138 double Query(int x){ 139 using namespace TC; 140 LL ans=0,sz=0; 141 int rt=nowroot; 142 if(rt==x)ans=qsum(1,n,1,n,1),sz=n; 143 else if(ind[x]<ind[rt] && out[rt]<=out[x]){ 144 rt=LCA(rt,x); 145 ans+=qsum(1,ind[rt]-1,1,n,1); 146 ans+=qsum(out[rt]+1,n,1,n,1); 147 sz=n-(out[rt]-ind[rt]+1); 148 } 149 else{ 150 ans=qsum(ind[x],out[x],1,n,1),sz=out[x]-ind[x]+1; 151 } 152 double res=(double)ans/(double)sz; 153 printf("%.10f\n",res); 154 return res; 155 } 156 #undef lc 157 #undef rc 158 }sgt; 159 struct LCT{ 160 int ch[mxn][2],fa[mxn]; 161 bool rev[mxn]; 162 int st[mxn],top; 163 inline bool isroot(int x){return (ch[fa[x]][0]!=x && ch[fa[x]][1]!=x);} 164 void PD(int rt){ 165 if(rev[rt]){ 166 rev[ch[rt][0]]^=1; rev[ch[rt][1]]^=1; 167 swap(ch[rt][0],ch[rt][1]); 168 rev[rt]^=1; 169 } 170 return; 171 } 172 void rotate(int x){ 173 int y=fa[x],z=fa[y],lc,rc; 174 if(ch[y][0]==x)lc=0;else lc=1; rc=lc^1; 175 if(!isroot(y)) ch[z][ch[z][1]==y]=x; 176 fa[x]=z;fa[y]=x; 177 fa[ch[x][rc]]=y; 178 ch[y][lc]=ch[x][rc]; ch[x][rc]=y; 179 return; 180 } 181 void Splay(int x){ 182 st[top=1]=x; 183 for(int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i]; 184 while(top)PD(st[top--]); 185 while(!isroot(x)){ 186 int y=fa[x],z=fa[y]; 187 if(!isroot(y)){ 188 if((ch[z][0]==y)^(ch[y][0]==x))rotate(x); 189 else rotate(y); 190 } 191 rotate(x); 192 } 193 } 194 void access(int x){ 195 for(int y=0;x;x=fa[x]){ 196 Splay(x); 197 if(ch[x][1]){ 198 int now=ch[x][1]; PD(now); 199 while(ch[now][0]){now=ch[now][0];PD(now);} 200 sgt.Q_UPD(now,1); 201 } 202 if(y){ 203 int now=y; PD(now); 204 while(ch[now][0]){now=ch[now][0];PD(now);} 205 sgt.Q_UPD(now,-1); 206 } 207 ch[x][1]=y; 208 y=x; 209 } 210 return; 211 } 212 void mkroot(int x){ 213 access(x);Splay(x); 214 rev[x]^=1; 215 nowroot=x; 216 return; 217 } 218 }LT; 219 void solve(){ 220 char opt[10];int x; 221 while(m--){ 222 scanf("%s%d",opt,&x); 223 if(opt[2]=='Q'){sgt.Query(x);continue;}//REQUEST 224 else if(opt[2]=='C'){LT.mkroot(x);continue;}//RECENTER 225 else if(opt[2]=='L'){LT.access(x);continue;}//RELEASE 226 // else Debug(); 227 } 228 return; 229 } 230 int main(){ 231 int i,j; 232 n=read();m=read(); 233 int u,v; 234 for(i=1;i<n;i++){ 235 u=read();v=read(); 236 add_edge(u,v);add_edge(v,u); 237 } 238 TC::DFS(1,0); 239 TC::DFS2(1,1); 240 for(i=1;i<=n;i++) LT.fa[i]=TC::t[i].fa; 241 sgt.Build(1,n,1); 242 nowroot=1; 243 solve(); 244 return 0; 245 }
Submit: 408 Solved: 163
[Submit][Status][Discuss]
Description
黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒。这种病毒的繁殖和变异能力极强。为了阻止这种病毒传播,某安全机构策划了一次实验,来研究这种病毒。
实验在一个封闭的局域网内进行。局域网内有n台计算机,编号为1~n。一些计算机之间通过网线直接相连,形成树形的结构。局域网中有一台特殊的计算机,称之为核心计算机。根据一些初步的研究,研究员们拟定了一个一共m步的实验。实验开始之前,核心计算机的编号为1,每台计算机中都有病毒的一个变种,而且每台计算机中的变种都不相同。实验中的每一步会是下面中的一种操作:
1、 RELEASE x
在编号为x的计算机中植入病毒的一个新变种。这个变种在植入之前不存在于局域网中。
2、 RECENTER x
将核心计算机改为编号为x的计算机。但是这个操作会导致原来核心计算机中的病毒产生新变种,并感染过来。换言之,假设操作前的核心计算机编号为y,相当于在操作后附加了一次RELEASE y的操作。
根据研究的结论,在植入一个新变种时,病毒会在局域网中搜索核心计算机的位置,并沿着网络中最短的路径感染过去。
而第一轮实验揭露了一个惊人的真相:病毒的不同变种是互斥的。新变种在感染一台已经被旧变种感染的电脑时,会把旧变种完全销毁之后再感染。但研究员发现了实现过程中的漏洞。如果新变种在感染过程中尚未销毁过这类旧变种,需要先花费1单位时间分析旧变种,才能销毁。如果之前销毁过这类旧变种,就可以认为销毁不花费时间。病毒在两台计算机之间的传播亦可认为不花费时间。
研究员对整个感染过程的耗时特别感兴趣,因为这是消灭病毒的最好时机。于是在m步实验之中,研究员有时还会做出如下的询问:
3、 REQUEST x
询问如果在编号为x的计算机的关键集合中的计算机中植入一个新变种,平均感染时间为多长。编号为y的计算机在编号为x的计算机的关键集合中,当且仅当从y沿网络中的最短路径感染到核心计算机必须经过x。由于有RECENTER操作的存在,这个集合并不一定是始终不变的。
至此,安全机构认为已经不需要实际的实验了,于是他们拜托你编写一个程序,模拟实验的结果,并回答所有的询问。
实验在一个封闭的局域网内进行。局域网内有n台计算机,编号为1~n。一些计算机之间通过网线直接相连,形成树形的结构。局域网中有一台特殊的计算机,称之为核心计算机。根据一些初步的研究,研究员们拟定了一个一共m步的实验。实验开始之前,核心计算机的编号为1,每台计算机中都有病毒的一个变种,而且每台计算机中的变种都不相同。实验中的每一步会是下面中的一种操作:
1、 RELEASE x
在编号为x的计算机中植入病毒的一个新变种。这个变种在植入之前不存在于局域网中。
2、 RECENTER x
将核心计算机改为编号为x的计算机。但是这个操作会导致原来核心计算机中的病毒产生新变种,并感染过来。换言之,假设操作前的核心计算机编号为y,相当于在操作后附加了一次RELEASE y的操作。
根据研究的结论,在植入一个新变种时,病毒会在局域网中搜索核心计算机的位置,并沿着网络中最短的路径感染过去。
而第一轮实验揭露了一个惊人的真相:病毒的不同变种是互斥的。新变种在感染一台已经被旧变种感染的电脑时,会把旧变种完全销毁之后再感染。但研究员发现了实现过程中的漏洞。如果新变种在感染过程中尚未销毁过这类旧变种,需要先花费1单位时间分析旧变种,才能销毁。如果之前销毁过这类旧变种,就可以认为销毁不花费时间。病毒在两台计算机之间的传播亦可认为不花费时间。
研究员对整个感染过程的耗时特别感兴趣,因为这是消灭病毒的最好时机。于是在m步实验之中,研究员有时还会做出如下的询问:
3、 REQUEST x
询问如果在编号为x的计算机的关键集合中的计算机中植入一个新变种,平均感染时间为多长。编号为y的计算机在编号为x的计算机的关键集合中,当且仅当从y沿网络中的最短路径感染到核心计算机必须经过x。由于有RECENTER操作的存在,这个集合并不一定是始终不变的。
至此,安全机构认为已经不需要实际的实验了,于是他们拜托你编写一个程序,模拟实验的结果,并回答所有的询问。
Input
输入的第一行包含两个整数n和m,分别代表局域网中计算机的数量,以及操作和询问的总数。
接下来n-1行,每行包含两个整数x和y,表示局域网中编号为x和y的计算机之间有网线直接相连。
接下来m行,每行包含一个操作或者询问,格式如问题描述中所述。
接下来n-1行,每行包含两个整数x和y,表示局域网中编号为x和y的计算机之间有网线直接相连。
接下来m行,每行包含一个操作或者询问,格式如问题描述中所述。
Output
对于每个询问,输出一个实数,代表平均感染时间。输出与答案的绝对误差不超过 10^(-6)时才会被视为正确。
Sample Input
8 6
1 2
1 3
2 8
3 4
3 5
3 6
4 7
REQUEST 7
RELEASE 3
REQUEST 3
RECENTER 5
RELEASE 2
REQUEST 1
1 2
1 3
2 8
3 4
3 5
3 6
4 7
REQUEST 7
RELEASE 3
REQUEST 3
RECENTER 5
RELEASE 2
REQUEST 1
Sample Output
4.0000000000
2.0000000000
1.3333333333
2.0000000000
1.3333333333
HINT
N < = 1 00 000 M < = 1 00 000
本文为博主原创文章,转载请注明出处。