题解 CF960H 【Santa's Gift】
柿子裂开以后维护和
标记下传自己拆开(x+y)^2的柿子就可以yy出来了
#include<cstdio>
#define int long long
#define db double
using namespace std;
inline int read(){int x=0,f=1,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;}
const int N=1e5+5;
int rt[N],c[N],n,m,q,C,f[N],head[N],tot;
struct edge{
int link,next;
}e[N<<1];
inline void add_edge(int u,int v){e[++tot]=(edge){v,head[u]}; head[u]=tot;}
inline void insert(int u,int v){add_edge(u,v); add_edge(v,u);}
inline void init(){
n=read(); m=read(); q=read(); C=read();
for (int i=1;i<=n;i++) f[i]=read();
for (int i=2;i<=n;i++) insert(read(),i);
}
struct node{
int sum1,sum2,son[2],plu;
}a[N*100];
int fa[N],cnt,sz[N],Son[N],top[N],dfn[N],pos[N];
void dfs(int u,int Fa){
fa[u]=Fa; sz[u]=1;
for (int i=head[u];i;i=e[i].next){
int v=e[i].link;
if (v!=Fa) {
dfs(v,u),sz[u]+=sz[v];
if (!Son[u]||sz[Son[u]]<Son[v]) Son[u]=v;
}
}
}
inline int sqr(int x){return x*x;}
inline void pushup(int k){
int l=a[k].son[0],r=a[k].son[1];
a[k].sum1=a[l].sum1+a[r].sum1;
a[k].sum2=a[l].sum2+a[r].sum2;
}
inline void plus(int &k,int l,int r,int w){
if (!k) k=++cnt; a[k].plu+=w; int sz=r-l+1;
a[k].sum2+=a[k].sum1*w+sz*sqr(w); a[k].sum1+=sz*w*2;
}
inline void pushdown(int k,int l,int mid,int r){
if (a[k].plu){
plus(a[k].son[0],l,mid,a[k].plu);
plus(a[k].son[1],mid+1,r,a[k].plu);
a[k].plu=0;
}
}
void update(int &k,int l,int r,int x,int y,int w){
if (!k) k=++cnt;
if (l==r) {plus(k,l,r,w); return;}
int mid=(l+r)>>1; pushdown(k,l,mid,r);
if (mid>=y) update(a[k].son[0],l,mid,x,y,w);
else if (mid<x) update(a[k].son[1],mid+1,r,x,y,w);
else update(a[k].son[0],l,mid,x,mid,w),update(a[k].son[1],mid+1,r,mid+1,y,w);
pushup(k);
}
void Dfs(int u,int tp){
dfn[u]=++tot; top[u]=tp; pos[tot]=u;
if (Son[u]) Dfs(Son[u],tp);
for (int i=head[u];i;i=e[i].next){
int v=e[i].link;
if (v!=Son[u]&&v!=fa[u]) Dfs(v,v);
}
}
inline void Update(int x,int opt,int w){
for (;x;x=fa[top[x]]){
int L=dfn[top[x]],R=dfn[x]; update(rt[opt],1,n,L,R,w);
}
}
inline int calc(int x){
return sqr(c[x])*a[rt[x]].sum2-a[rt[x]].sum1*C*c[x]+n*sqr(C);
}
inline void solve(){
tot=0; dfs(1,0); Dfs(1,1);
for (int i=1;i<=m;i++) c[i]=read();
for (int i=1;i<=n;i++) Update(i,f[i],1);
for (int i=1;i<=q;i++){
int opt=read(),x=read(),y;
if (opt==1) {
y=read(); Update(x,f[x],-1); Update(x,f[x]=y,1);
}else{
int tmp=calc(x);
printf("%.7lf\n",(db)tmp/(db)n);
}
}
}
signed main(){
init();
solve();
return 0;
}