【Codeforces960H】 Santa's Gift

time limit per test:4 seconds
memory limit per test:512 megabytes
standard input
standard output

Description
Santa has an infinite number of candies for each of m flavours. You are given a rooted tree with n vertices. The root of the tree is the vertex 1. Each vertex contains exactly one candy. The i-th vertex has a candy of flavour fi.

Sometimes Santa fears that candies of flavour k have melted. He chooses any vertex x randomly and sends the subtree of x to the Bakers for a replacement. In a replacement, all the candies with flavour k are replaced with a new candy of the same flavour. The candies which are not of flavour k are left unchanged. After the replacement, the tree is restored.

The actual cost of replacing one candy of flavour k is ck (given for each k). The Baker keeps the price fixed in order to make calculation simple. Every time when a subtree comes for a replacement, the Baker charges C, no matter which subtree it is and which flavour it is.

Suppose that for a given flavour k the probability that Santa chooses a vertex for replacement is same for all the vertices. You need to find out the expected value of error in calculating the cost of replacement of flavour k. The error in calculating the cost is defined as follows.

Error E(k)= (ActualCost – Price charged by the Bakers)2.
Note that the actual cost is the cost of replacement of one candy of the flavour k multiplied by the number of candies in the subtree.

Also, sometimes Santa may wish to replace a candy at vertex x with a candy of some flavour from his pocket.

You need to handle two types of operations:

Change the flavour of the candy at vertex x to w.
Calculate the expected value of error in calculating the cost of replacement for a given flavour k.

Input
The first line of the input contains four integers
n
n (2n5104) ( 2   ≤   n   ≤   5 ⋅ 10 4 ) , m, q, C (1m,q5104,0leqC106) ( 1   ≤   m , q   ≤   5 ⋅ 10 4 , 0 l e q C ≤ 10 6 ) — the number of nodes, total number of different flavours of candies, the number of queries and the price charged by the Bakers for replacement, respectively.

The second line contains n integers f1,f2,…,fn (1⩽fi⩽m), where fi is the initial flavour of the candy in the i-th node.

The third line contains n−1 integers p2,p3,…,pn (1⩽pi⩽n), where pi is the parent of the i-th node.

The next line contains m integers c1,c2,…cm (1⩽ci⩽102), where ci is the cost of replacing one candy of flavour i.

The next q lines describe the queries. Each line starts with an integer 1 ⩽ t ⩽ 2) — the type of the query.

If t = 1, then the line describes a query of the first type. Two integers x and w follow (1 ⩽ x⩽ n, 1⩽ w⩽ m), it means that Santa replaces the candy at vertex x with flavour w.

Otherwise, if t=2, the line describes a query of the second type and an integer k (1 ⩽ k ⩽ m) follows, it means that you should print the expected value of the error in calculating the cost of replacement for a given flavour k.

The vertices are indexed from 1 to n. Vertex 1 is the root.

Output
Output the answer to each query of the second type in a separate line.

Your answer is considered correct if its absolute or relative error does not exceed 106 10 − 6 .

Formally, let your answer be a, and the jury’s answer be b. The checker program considers your answer correct if and only if |a−b|max(1,b)⩽10−6.

Example
input1

3 5 5 7
3 1 4
1 1
73 1 48 85 89
2 1
2 3
1 2 3
2 1
2 3

output1

2920.333333333333
593.000000000000
49.000000000000
3217.000000000000

题目大意给出n个节点以1为根的树,和一个参数C
每个节点有一个标号fi,范围为1~m,每种标号有一个权值ci,现在让你维护修改操作与查询操作
修改一个点的标号
或给出一个k,令当前树中节点i Cnti C n t i 为i的子树中标号为k的个数
ni=1(Cntic[k]C)2n ∑ i = 1 n ( C n t i c [ k ] − C ) 2 n


Analysis
拆开式子 Cnt2ic[k]22CntiCc[k]+C2 ∑ C n t i 2 c [ k ] 2 − 2 C n t i C c [ k ] + C 2
对每种标号建棵动态开点的线段树,树链剖分,维护那几个和,平方和即可

我终于找到了树链剖分的正确打开方式。。。弄出重儿子之后先走重儿子搞出dfs序,这样就可以区间修改啦。。。

注意down也要开点

code

#include<iostream>
#include<cstring>
#include<cstdio>
#include<iomanip>
#define N 100100
#define ll long long
#define db long double

using namespace std;

int n,m,q,top[N],hvy[N],fir[N],to[N],nex[N],cnt,son[N*100][2],rt[N],siz[N],f[N],dfn[N],fa[N],opl,opr,opp;
ll s[N*100],s2[N*100],C,c[N],add[N*100],opv;

void dfs(int x){
    siz[x]=1;int mx=0,p=0;
    for(int i=fir[x];i;i=nex[i]){
        int v=to[i];dfs(v);siz[x]+=siz[v];if(siz[v]>mx)mx=siz[v],p=v;
    }hvy[x]=p;
}
void make(int x){
    dfn[x]=++cnt;top[hvy[x]]=top[x];if(hvy[x])make(hvy[x]);
    for(int i=fir[x];i;i=nex[i])if(to[i]!=hvy[x])top[to[i]]=to[i],make(to[i]);
}

void pl(int &w,int h,int t,int k){
    if(!w)w=++cnt;add[w]+=k;
    s2[w]+=s[w]*k+(ll)(t-h+1)*k*k;s[w]+=(ll)(t-h+1)*k*2;
}
void down(int w,int h,int t){
    int m=h+t>>1;
    if(add[w]){pl(son[w][0],h,m,add[w]);pl(son[w][1],m+1,t,add[w]);add[w]=0;}
}
void update(int w){
    int l=son[w][0],r=son[w][1];
    s2[w]=s2[l]+s2[r];s[w]=s[l]+s[r];
}
void inc(int &w,int h,int t){
    if(opl>opr)return;
    if(!w)w=++cnt;
    if(opl<=h && opr>=t){pl(w,h,t,opp);return;}
    down(w,h,t);int m=h+t>>1;
    if(opl<=m)inc(son[w][0],h,m);if(opr>m)inc(son[w][1],m+1,t);
    update(w);
}
void put(int v,int w,int k){
    for(;w;w=fa[top[w]]){
        opl=dfn[top[w]];opr=dfn[w];opv=c[v];opp=k;inc(rt[v],1,n);
    }
}

ll calc(int w){
    return c[w]*c[w]*s2[rt[w]]-s[rt[w]]*C*c[w]+(ll)n*C*C;
}

int main(){
    scanf("%d %d %d %I64d",&n,&m,&q,&C);
    for(int i=1;i<=n;i++)scanf("%d",&f[i]);
    for(int i=2;i<=n;i++){
        scanf("%d",&fa[i]);to[i]=i;nex[i]=fir[fa[i]];fir[fa[i]]=i;
    }dfs(1);top[1]=1;make(1);cnt=m;
    for(int i=1;i<=m;i++)rt[i]=i;
    for(int i=1;i<=m;i++)scanf("%I64d",&c[i]);
    for(int i=1;i<=n;i++)put(f[i],i,1);
    for(int i=1;i<=q;i++){
        int x,w,s;scanf("%d %d",&s,&x);
        if(s==1){
            scanf("%d",&w);put(f[x],x,-1);put(f[x]=w,x,1);
        }else{
            cout<<setprecision(20)<<(db)calc(x)/(db)n<<endl;
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值