当前位置: 代码迷 >> 综合 >> [Codeforces1046D][BFS序][树状数组]Interstellar battle
  详细解决方案

[Codeforces1046D][BFS序][树状数组]Interstellar battle

热度:41   发布时间:2023-12-19 05:06:50.0

翻译

给出一棵树以及树上的点消失的概率
Q次修改
每次修改一个点消失的概率
问每次修改之后当前树剩下的连通块个数的期望
Q<=200000 N<=100000

题解

通过这题gay到了一个新姿势:
树上连通块个数=点数-边数
相当于动态维护一个 E ( V ? E ) E(V-E) E(V?E)
根据期望的线性性,上式可以写为 E ( V ) ? E ( E ) E(V)-E(E) E(V)?E(E)
可以先将消失的概率转化为存在的概率 记为 c a l [ i ] cal[i] cal[i]
显然 E ( V ) = ∑ c a l [ i ] E(V)=\sum cal[i] E(V)=cal[i]
下来考虑动态维护 E ( E ) E(E) E(E)
我们考虑一条边存在的期望 当且仅当它所连接的两个点均没消失 记这两点为 ( u , v ) (u,v) (u,v)
则一条边 K K K存在的期望为 E ( u ) ? E ( v ) E(u)*E(v) E(u)?E(v)
相当于维护一个 ∑ E ( u ) ? E ( v ) \sum E(u)*E(v) E(u)?E(v)
考虑一个点被修改的影响
只会影响与他相连的边
这些边可以分为两类 一类连向儿子一类连向父亲虽然父亲只有一条边
父亲这条边的贡献可以暴力改掉
搞出BFS序 显然一个点的所有儿子的BFS序是连续的
树状数组乱撸

#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<vector> #define LL long long #define mp(x,y) make_pair(x,y) using namespace std; inline int read() {
     int f=1,x=0;char ch=getchar();while(ch<'0'||ch>'9'){
     if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){
     x=x*10+ch-'0';ch=getchar();}return x*f; } inline void write(int x) {
     if(x<0)putchar('-'),x=-x;if(x>9)write(x/10);putchar(x%10+'0'); } inline void print(int x){
     write(x);printf(" ");} struct node{
     int x,y,next;}a[210000];int len,last[110000]; void ins(int x,int y){
     len++;a[len].x=x;a[len].y=y;a[len].next=last[x];last[x]=len;} queue<int> li; int fa[110000]; void pre_tree_node(int x) {
     for(int k=last[x];k;k=a[k].next)if(a[k].y!=fa[x])fa[a[k].y]=x,pre_tree_node(a[k].y); } int in[110000],ot[110000],deg[110000],bfn; int fir[110000]; void init_BFS() {
     li.push(1);in[1]=++bfn;while(!li.empty()){
     int x=li.front();fir[x]=bfn;for(int k=last[x];k;k=a[k].next)if(a[k].y!=fa[x]){
     int y=a[k].y;in[y]=++bfn;li.push(y); }li.pop();ot[x]=bfn;} } double s[110000]; int n,T; int lowbit(int x){
     return x&-x;} void change(int x,double c){
     for(int i=x;i<=n;i+=lowbit(i))s[i]+=c;} double findsum(int x){
     double ret=0;for(int i=x;i>=1;i-=lowbit(i))ret+=s[i];return ret;} double cal[110000]; int main() {
     n=read();for(int i=1;i<=n;i++)scanf("%lf",&cal[i]),cal[i]=1.0-cal[i];for(int i=1;i<n;i++){
     int x=read(),y=read();x++;y++;ins(x,y);ins(y,x);}pre_tree_node(1);init_BFS();for(int i=1;i<=n;i++)change(in[i],cal[i]);T=read();double s1=0,s2=0;for(int i=1;i<=n;i++)s1+=cal[i];for(int i=1;i<=n;i++){
     double S=findsum(ot[i])-findsum(fir[i]);s2+=cal[i]*S;}//printf("%.5lf\n",s1-s2);while(T--){
     int x=read();double c;scanf("%lf",&c);c=1-c;x++;s1-=cal[x];s1+=c;double S=findsum(ot[x])-findsum(fir[x]);s2-=cal[x]*S;s2+=c*S;s2-=cal[x]*cal[fa[x]];s2+=c*cal[fa[x]];change(in[x],-cal[x]+c);cal[x]=c;printf("%.5lf\n",s1-s2);}return 0; }