zoukankan      html  css  js  c++  java
  • [四校联考]约会

    Description

    羊驼非常喜欢菠萝,他们虽然身处异地(即他们不会处在同一个树节点上),但经常到某地约会。 他们所处的世界是一棵以1为根的树,这棵树上的每个节点都有一个权值Wi,并且他们约会时会到他们各自所在节点的最近公共祖先(lca)上,假设他们分别处于x节点和y节点,他们的花费的代价就是\(W_x+W_y\),有时某个节点的权值会改加上某个数,有时某个节点的子树都会加上某个数。 现在他们向你寻求帮助,他想知道当他们约会的地点为z(即lca为z时),求他们花费的期望代价。

    Input

    第一行输入一个整数n,m,n是节点个数,m是操作总数。
    第二行读入n-1个整数\(f_i\),表示2-n节点的父亲。
    第三行读入n个整数\(s_i\),表示n个节点一开始的权值。
    接下来m行,一共有三种操作。
    “S x s”节点x的权值加上s。
    “M x s”节点x的子树(包括自己本身)每个节点都加上s。
    “Q x”查询他们约会的地点为z(即lca为z)时,求花费的期望代价。

    Output

    对于每一个Q输出一个实数ans,绝对误差在\(10^{-4}\)以内就视为正确。

    Sample Input

    5 4
    1 1 1 1
    1 2 2 3 3
    Q 1
    S 1 4
    M 1 -2
    Q 1
    

    Sample Output

    4.400000
    2.000000
    

    HINT

    \(n,m\leq300000,-10^5\leq{s}\leq10^5\).

    Solution

    \(u\) 为根的子树对父亲 \(f\) 的贡献为\(\sum{s_i}\times{siz[f]-siz[u]}\).

    对树进行轻重链剖分,对于每个询问,\(\sum\varDelta{s_i}\)是固定的.

    除了\(x\)之外,其他改变的贡献均为\(\sum\varDelta{s_i}\times{siz[f]-siz[u]}\)

    对于轻链直接暴力修改,重链线段树维护 \(siz[f]-siz[son[f]]\) 及相关值即可.

    #define N 300005
    #define M 3000005
    typedef long long ll;
    struct graph{
    	int nxt,to;
    }e[N];
    ll s[N],tot[N],ans[N];
    int dep[N],siz[N],son[N],top[N];
    int g[N],f[N],w[N],p[N],n,m,cnt;
    inline void addedge(int x,int y){
    	e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;
    }
    inline void dfs1(int u){
    	int mx=0;siz[u]=1;
    	for(int i=g[u],c;i;i=e[i].nxt){
    		f[c=e[i].to]=u;
    		dep[c]=dep[u]+1;dfs1(c);
    		siz[u]+=siz[c];
    		if(siz[c]>mx){
    			mx=siz[c];son[u]=c;
    		}
    	}
    }
    inline void dfs2(int u,int tp){
    	int c;
    	tot[u]=1ll*(siz[u]-1);
    	ans[u]=1ll*s[u]*(siz[u]-1);
    	p[u]=++cnt;w[cnt]=u;top[u]=tp;
    	if(c=son[u]){
    		dfs2(son[u],tp);
    		s[u]+=s[c];
    		ans[u]+=1ll*s[c]*(siz[u]-siz[c]);
    		tot[u]+=1ll*(siz[u]-siz[c])*siz[c];
    	}
    	for(int i=g[u];i;i=e[i].nxt)
    		if((c=e[i].to)!=son[u]) {
    			dfs2(c,c);
    			s[u]+=s[c];
    			ans[u]+=1ll*s[c]*(siz[u]-siz[c]);
    			tot[u]+=1ll*(siz[u]-siz[c])*siz[c];
    		}
    	tot[u]>>=1;
    }
    struct SegMent{
    	int l,r;ll sum/*ans*/,lzy/**/,lzt/*tot[u]<<1*/;
    }lt[M];
    inline void build(int u,int l,int r){
    	lt[u].l=l;lt[u].r=r;
    	if(lt[u].l<lt[u].r){
    		int lef=u<<1,rig=u<<1|1;
    		int mid=(lt[u].l+lt[u].r)>>1;
    		build(lef,l,mid);build(rig,mid+1,r);
    	}
    	else{
    		int p=w[lt[u].l];
    		lt[u].sum=ans[p];
    	}
    }
    inline void pushdown(int u){
    	if(!lt[u].lzy&&!lt[u].lzt) return;
    	if(lt[u].l<lt[u].r){
    		int lef=u<<1,rig=u<<1|1;ll s;
    		s=lt[u].lzy;lt[lef].lzy+=s;lt[rig].lzy+=s;
    		s=lt[u].lzt;lt[lef].lzt+=s;lt[rig].lzt+=s;
    	}
    	else{
    		ll s=lt[u].lzy;int p=w[lt[u].l];
    		lt[u].sum+=1ll*(siz[p]-siz[son[p]])*s;
    		s=lt[u].lzt;lt[u].sum+=1ll*(tot[p]<<1ll)*s;
    	}
    	lt[u].lzy=lt[u].lzt=0;
    }
    inline void add_s(int u,int l,int r,ll s){
    	if(lt[u].l>=l&&lt[u].r<=r){
    		lt[u].lzy+=s;return;
    	}
    	if(lt[u].l<lt[u].r){
    		int lef=u<<1,rig=u<<1|1;
    		int mid=(lt[u].l+lt[u].r)>>1;
    		if(l<=mid) add_s(lef,l,r,s);
    		if(r>mid) add_s(rig,l,r,s);
    	}
    }
    inline void add_t(int u,int l,int r,ll s){
    	if(lt[u].l>=l&&lt[u].r<=r){
    		lt[u].lzt+=s;return;
    	}
    	if(lt[u].l<lt[u].r){
    		int lef=u<<1,rig=u<<1|1;
    		int mid=(lt[u].l+lt[u].r)>>1;
    		if(l<=mid) add_t(lef,l,r,s);
    		if(r>mid) add_t(rig,l,r,s);
    	}
    }
    inline void add(int u,int x,ll s){
    	pushdown(u);
    	if(lt[u].l==lt[u].r){
    		lt[u].sum+=s;return;
    	}
    	if(lt[u].l<lt[u].r){
    		int lef=u<<1,rig=u<<1|1;
    		int mid=(lt[u].l+lt[u].r)>>1;
    		if(x<=mid) add(lef,x,s);
    		else add(rig,x,s);
    	}
    }
    inline ll ask(int u,int x){
    	pushdown(u);
    	if(lt[u].l==lt[u].r)
    		return lt[u].sum;
    	if(lt[u].l<lt[u].r){
    		int lef=u<<1,rig=u<<1|1;
    		int mid=(lt[u].l+lt[u].r)>>1;
    		if(x<=mid) return ask(lef,x);
    		return ask(rig,x);
    	}
    }
    inline void change(int u,int lst,ll s){
    	if(!u) return;
    	if(lst==top[lst]){
    		add(1,p[u],1ll*s*(siz[u]-siz[lst]));
    		if(p[top[u]]<p[u])
    			add_s(1,p[top[u]],p[u]-1,s);
    	}
    	else add_s(1,p[top[u]],p[u],s);
    	lst=top[u];u=f[top[u]];
    	while(u){
    		add(1,p[u],1ll*s*(siz[u]-siz[lst]));
    		if(p[top[u]]<p[u])
    			add_s(1,p[top[u]],p[u]-1,s);
    		lst=top[u];u=f[top[u]];
    	}
    }
    inline void Aireen(){
    	n=read();m=read();
    	for(int i=2;i<=n;++i) addedge(read(),i);
    	for(int i=1;i<=n;++i) s[i]=1ll*read();
    	dep[1]=1;dfs1(1);
    	cnt=0;dfs2(1,1);build(1,1,n);
    	char c[2];int x,s;
    	while(m--){
    		scanf("%s",&c);x=read();
    		if(c[0]=='S') s=read(),add(1,p[x],1ll*(siz[x]-1)*s),change(f[x],x,1ll*s);
    		else if(c[0]=='M') s=read(),add_t(1,p[x],p[x]+siz[x]-1,s),change(f[x],x,1ll*s*siz[x]);
    		else printf("%lf\n",(double)(ask(1,p[x]))/(double)(tot[x]));
    	}
    }
    

    2017-04-20 19:53:21

  • 相关阅读:
    【译文】不是所有的 bug 都值得修复的
    11月第5周业务风控关注|重磅!瓜子二手车“遥遥领先”被罚天价1250万
    AutoCAD .NET二次开发(四)
    AutoCAD .NET二次开发(三)
    ArcGIS10.2下调试10.1的程序
    再遇1402,注册表权限问题
    ArcGIS Add-in——自动保存编辑
    只打开一个子窗体
    获取编辑器两种方法
    Adobe Acrobat Pro 11安装激活
  • 原文地址:https://www.cnblogs.com/AireenYe/p/15602996.html
Copyright © 2011-2022 走看看