zoukankan      html  css  js  c++  java
  • bzoj3683: Falsita

    题解: 我们考虑不待修改的情况 sigma(sz[x]-sz[y])*(sum[y])+(sz[x]-1)*v[x]  直接一遍dfs处理即可 分母部分同样mu[x]=sz[x]^2-1-sigma(sz[y]^2) 然后我们考虑单点修改的情况 对于当前这个点x 它对应的ans[x]+=delet*(sz[x]-1) 对于这个节点到根路径上的点 delet*(sz[y]-sz[x])(x是路径上的点且是y的儿子节点) 那么我们考虑把这一段用重链剖开 对于重链重链交接的点特殊处理 其他的用两个树状数组维护k*delet*(sz[x]-sz[son[x])(k为被修改的节点个数)和区间加的这段区间delet*mu[x]即可

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <stack>
    #include <queue>
    #include <cmath>
    #include <set>
    #include <map>
    #define mp make_pair
    #define pb push_back
    #define pii pair<int,int>
    #define link(x) for(edge *j=h[x];j;j=j->next)
    #define inc(i,l,r) for(int i=l;i<=r;i++)
    #define dec(i,r,l) for(int i=r;i>=l;i--)
    const int MAXN=3e5+10;
    const double eps=1e-8;
    #define ll long long
    using namespace std;
    struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
    void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    ll ans[MAXN],mu[MAXN],sum[MAXN],a[MAXN];
    int dep[MAXN],fa[MAXN],son[MAXN],num[MAXN],n;
    void dfs(int x,int pre,int deep){
    	num[x]=1;dep[x]=deep+1;fa[x]=pre;
    	link(x){
    		if(j->t!=pre){
    			dfs(j->t,x,deep+1);
    			num[x]+=num[j->t];sum[x]+=sum[j->t];ans[x]-=1ll*num[j->t]*sum[j->t];
    			if(son[x]==-1||num[son[x]]<num[j->t])son[x]=j->t;
    			mu[x]-=1ll*num[j->t]*num[j->t];
    		}
    	}
    	mu[x]+=1ll*num[x]*num[x]-1;
    	ans[x]+=1ll*num[x]*sum[x]-a[x];
    }
    int p[MAXN],tp[MAXN],fp[MAXN],cnt;
    void dfs1(int x,int td){
    	p[x]=++cnt;fp[p[x]]=x;tp[x]=td;
    	if(son[x]!=-1)dfs1(son[x],td);
    	link(x){
    		if(j->t!=fa[x]&&j->t!=son[x])dfs1(j->t,j->t);
    	}
    }
    ll sum1[MAXN],sum2[MAXN];
    int get_id(int x){return x&(-x);}
    void update1(int x,ll key){
    	for(int i=x;i<=n+1;i+=get_id(i))sum1[i]+=key;
    }
    ll Sum1(int x){
    	ll ans1=0;
    	for(int i=x;i>0;i-=get_id(i))ans1+=sum1[i];
    	return ans1;
    }
    void slove(int u,int v,ll key){
    	if(son[fa[u]]!=u){
    		ans[fa[u]]+=1ll*key*(num[fa[u]]-num[u]);
    		u=fa[u];
    	}
    	u=fa[u];
    	if(!u)return ;
    	int uu=tp[u];int vv=tp[v],last=0;
    	while(uu!=vv){
    		update1(p[uu],key);update1(p[u]+1,-key);
    		u=fa[uu];last=uu;uu=tp[u];
    		if(uu!=vv){
    			ans[u]+=1ll*key*(num[u]-num[last]);
    			u=fa[u];uu=tp[u];
    		}
    	}
    	if(last){
    		ans[u]+=1ll*key*(num[u]-num[last]);
    		u=fa[u];
    	}
    	if(u){
    		update1(p[1],key);update1(p[u]+1,-key);
    	}
    }
    void update2(int x,ll key){
    	for(int i=x;i<=n+1;i+=get_id(i))sum2[i]+=key;
    }
    ll Sum2(int x){
    	ll ans2=0;
    	for(int i=x;i>0;i-=get_id(i))ans2+=sum2[i];
    	return ans2;
    }
    int main(){
    	n=read();int m=read();
    	int u,v;char ch;ll key;
    	inc(i,2,n)u=read(),add(u,i);
    	inc(i,1,n)a[i]=sum[i]=read(),son[i]=-1;
    	dfs(1,0,0);dfs1(1,1);
    	while(m--){
    		scanf(" %c",&ch);
    		if(ch=='S'){
    			v=read();key=read();
    			ans[v]+=1ll*(num[v]-1)*key;
    			slove(v,1,key);
    		}
    		else if(ch=='M'){
    			v=read();key=read();
    			update2(p[v],key);update2(p[v]+num[v],-key);
    			slove(v,1,1ll*num[v]*key);
    		}
    		else{
    			v=read();
    			ll ans1=Sum1(p[v]);ans1=1ll*ans1*(num[v]-num[son[v]]);
    			ll ans2=Sum2(p[v]);ans2=1ll*ans2*mu[v];
    			ll ans3=2*(ans[v]+ans2+ans1);
    			printf("%.6f
    ",ans3*1.0/mu[v]);
    		}
    	}
    	return 0;
    }
    

     

    3683: Falsita

    Time Limit: 20 Sec  Memory Limit: 256 MBSec  Special Judge
    Submit: 340  Solved: 137
    [Submit][Status][Discuss]

    Description

    描述
    到海边了呢......
    如果没有那次选择,现在是不是会好些呢......
    都过去了。
    仰望着星空,迎面吹过一阵阵海风,倚靠着护栏,Fine 在海边静静地伫立着,在一个个无际的长夜后,Fine 终于放下了往事的痛楚,得到了治愈。
    但是作为 Fine 的另一重人格的 Falsita 就没那么幸运了。她仍然被各种繁忙的事务困扰着。
    虽然同在一副躯体中,Fine 与 Falsita 的精神世界却相差甚远,Fine 可以轻易地构造出幻梦时,Falsita 却只能停留在现实的痛楚中。
    但是为了生活需要,她们还是需要经常达成共识。
    让我们形式化的描述一下吧。
    她们所在的精神世界是一棵以 1 号节点为根的树,每个树上的节点 u 都有一个权值Wu,她们每个人分别都在一个节点上,达成共识的方法就是两个人都到达一个共识节点(即到达它们的最近公共祖先)。
    一个点 u 与另外一个点 v 之间想要达到共识需要花费的代价为Wu+Wv。
    有时两人的精神有所触动时,有时点的权值会改变成某个数,有时以某个点的子树中的所有点的权值会加上某个数。
    Falsita 和 Fine 经常需要达成共识,每一次询问,已知达成的共识节点,求她们花费的期望代价。

    Input

    输入共 m + 3 行。
    第一行两个整数 n, m ,表示节点个数和操作数。
    第二行 n - 1 个整数Pi,表示节点 i ( i = 2 . . . n ) 的父亲节点的编号。
    第三行 n 个整数Wi。
    接下来 m 行,每行表示一个操作。
    1. S u delta 表示将节点 u 的权值加上 delta 。
    2. M u delta 表示将以节点 u 为根的子树中的所有节点的权值加上 delta。
    3. Q u 表示询问共识节点为 u 时的答案。
    询问保证 u 不是叶子节点。

    Output

    对于每组询问,输出答案,答案精确到小数点后 6 位。
    你的程序输出的答案需要与标准答案之差不超过10^(-5)。

    Sample Input

    4 6
    1 2 2
    0 -6 3 0
    S 2 -5
    M 3 8
    S 1 -1
    M 4 7
    M 3 2
    Q 1

    Sample Output

    2.000000
  • 相关阅读:
    03 JVM 从入门到实战 | 简述垃圾回收算法
    02 JVM 从入门到实战 | 什么样的对象需要被 GC
    01 JVM 从入门到实战 | 什么是 JVM
    从一道面试题探究 Integer 的实现
    程序员如何写一份更好的简历
    自己动手实现分布式任务调度框架(续)
    一个excel(20M)就能干趴你的poi,你信吗?
    一个普通类就能干趴你的springboot,你信吗?
    自己动手实现springboot配置(非)中心
    自己动手实现分布式任务调度框架
  • 原文地址:https://www.cnblogs.com/wang9897/p/9912554.html
Copyright © 2011-2022 走看看