题解:P11824 [湖北省选模拟 2025] 团队协作 / team

· · 题解

当题解区全是线段树的时候,一篇树剖+线段树题解就是救赎!

Solution

Step 1

考虑转置原理,这里官方题解已经讲的很清楚了,所以适当省略。

这个题的矩阵 A_{i,j} 表示第 i 个人参与的最大值为 j 的任务个数。

转置之后就是 A^T_{i,j} 表示最大值为 i 的第 j 个人参与的方案个数。

转置之后的问题就是最大值为 i 每个人有权值 w 然后权值之和之和。

这个问题可以 DDP 做,每个重链开线段树,每个节点轻儿子开线段树(不需要操作的逆),记录每次操作,发现可以只有 x:=x+yv,x:=0 于是可以转置成 y:=y+xv,x:=0 然后所有操作逆序,就是原问题的算法。

record

#include<bits/stdc++.h>
using namespace std;
bool bg_memory;
chrono::_V2::system_clock::time_point bg_clock,en_clock;
void debugTime(){
    en_clock=chrono::high_resolution_clock::now();
    auto duration_clock=chrono::duration_cast<chrono::microseconds>(en_clock-bg_clock);
    double duration_count=duration_clock.count()*0.001;
    cerr<<"Time:"<<duration_count<<"ms"<<endl;
}
namespace GENSOKYO{
template<typename T>
void read(T &a){
    char c;a=0;int f=1;
    while(!isdigit(c=getchar()))if(c=='-')f=-1;
    do a=a*10+c-'0';
    while(isdigit(c=getchar()));
    a*=f;
}
template<typename T>
void write(T a){
    if(a<0)putchar('-'),a=-a;
    if(a>=10)write(a/10);
    putchar('0'+a%10);
}
char GC(){
    char c=getchar();
    while(c<=32)c=getchar();
    return c;
}
template<typename T1,typename T2>
void chmin(T1 &x,T2 y){if(x>y)x=y;}
template<typename T1,typename T2>
void chmax(T1 &x,T2 y){if(x<y)x=y;}
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef unsigned int ui;
typedef pair<int,int> PII;
typedef pair<ll,int> PLI;
typedef __int128 lll;
mt19937 rng(chrono::system_clock::now().time_since_epoch().count());
int RRand(int n){return (ull)rng()*n>>32;}
int RRand(int l,int r){return l+RRand(r-l+1);}
void gskinit(){
}
const int MAXN=300010;
const int P=998244353;
int n,fa[MAXN];
vector<int> G[MAXN];
int v[MAXN];
struct Op{
    int *x,*y,v;//x+=y*v;
    Op(){}
    Op(int *x,int *y,int v):x(x),y(y),v(v){}
};
struct Pr{
    int val,cnt;
    Pr(){cnt=1;}
};
struct Mat{
    Pr a[2][2];
    Mat(){a[1][0].cnt=a[1][1].cnt=0;}
};
Op seq[20000010];int scnt;
void add(int *x,int *y,int v){
    // scnt++;
    seq[scnt++]=Op(x,y,v);
}
void assign(int &A,int &B,int v=1){
    // scnt++;
    seq[scnt++]=Op(&A,&B,v==0?-P:-v);
}
void assign(Pr &A,Pr &B){
    assign(A.val,B.val);
    A.cnt=B.cnt;
}
void assign(Mat &A,Mat &B){
    for(int i=0;i<2;++i)
        for(int j=0;j<2;++j)
            assign(A.a[i][j],B.a[i][j]);
}
void Add(Pr &A,Pr &B,Pr &C){
    assign(A.val,B.val,1);
    add(&A.val,&C.val,1);
    A.cnt=(B.cnt+C.cnt)%P;
}
void Mult(Pr &A,Pr &B,Pr &C){
    assign(A.val,B.val,C.cnt);
    add(&A.val,&C.val,B.cnt);
    A.cnt=(ll)B.cnt*C.cnt%P;
}
void Mult(Mat &A,Mat &B,Mat &C){
    for(int i=0;i<2;++i)
        for(int j=0;j<2;++j){
            assign(A.a[i][j].val,B.a[i][0].val,C.a[0][j].cnt);
            add(&A.a[i][j].val,&C.a[0][j].val,B.a[i][0].cnt);
            add(&A.a[i][j].val,&B.a[i][1].val,C.a[1][j].cnt);
            add(&A.a[i][j].val,&C.a[1][j].val,B.a[i][1].cnt);
            A.a[i][j].cnt=((ll)B.a[i][0].cnt*C.a[0][j].cnt+(ll)B.a[i][1].cnt*C.a[1][j].cnt)%P;
        }
}
Pr ptmp1,ptmp2,ptmp3;
Mat mtmp1,mtmp2,mtmp3;
namespace SEGM{
int sgtot;
Mat t[MAXN<<2];
int ch[MAXN<<2][2];
#define mid (L+R>>1)
void build(int &x,int L,int R){
    if(!x)x=++sgtot;
    if(L==R){
    }else{
        build(ch[x][0],L,mid);
        build(ch[x][1],mid+1,R);
    }
}
void pushup(int x){
    Mult(t[x],t[ch[x][0]],t[ch[x][1]]);
}
void upd(int &x,int pos,Mat &v,int L,int R){
    if(L==R){
        assign(t[x],v);
    }else{
        if(pos<=mid)upd(ch[x][0],pos,v,L,mid);
        else upd(ch[x][1],pos,v,mid+1,R);
        pushup(x);
    }
}
#undef mid
}
namespace SEGP{
Pr a[MAXN<<2],b[MAXN<<2];int sgtot;
int ch[MAXN<<2][2];
// a: 0+1 ; b: 0
#define mid (L+R>>1)
void build(int &x,int L,int R){
    if(!x)x=++sgtot;
    if(L==R){
    }else{
        build(ch[x][0],L,mid);
        build(ch[x][1],mid+1,R);
    }
}
void pushup(int x){
    Mult(a[x],a[ch[x][0]],a[ch[x][1]]);
    Mult(b[x],b[ch[x][0]],b[ch[x][1]]);
}
void upd(int &x,int pos,Pr &A,Pr &B,int L,int R){
    if(L==R){
        assign(a[x],A);
        assign(b[x],B);
    }else{
        if(pos<=mid)upd(ch[x][0],pos,A,B,L,mid);
        else upd(ch[x][1],pos,A,B,mid+1,R);
        pushup(x);
    }
}
#undef mid
}
int siz[MAXN],hson[MAXN],top[MAXN],dfn[MAXN],fdfn[MAXN],bot[MAXN],dfc;
int lid[MAXN];//light son id
int hrt[MAXN],lrt[MAXN];// heavy chain segT ; light son segT
void dfs1(int x){
    siz[x]=1;hson[x]=0;
    for(int y:G[x]){
        dfs1(y);
        if(siz[y]>siz[hson[x]])hson[x]=y;
        siz[x]+=siz[y];
    }
}
void dfs2(int x,int topf){
    fdfn[dfn[x]=++dfc]=x;
    top[x]=topf;
    bot[top[x]]=x;
    if(hson[x])dfs2(hson[x],topf);
    for(int y:G[x])if(y!=hson[x]){
        dfs2(y,y);
    }
}
Pr c[MAXN];// the coefficient for vertex x
Mat d[MAXN];// the matrix for vertex x
int oans[MAXN];
void main(){
    read(n);
    for(int i=2;i<=n;++i){
        read(fa[i]);
        G[fa[i]].emplace_back(i);
    }
    for(int i=1;i<=n;++i)read(v[i]),c[i].cnt=0;
    vector<int> ord(n);
    for(int i=0;i<n;++i)ord[i]=i+1;
    sort(ord.begin(),ord.end(),[&](int x,int y){return v[x]<v[y];});
    dfs1(1),dfs2(1,1);
    for(int i=1;i<=n;++i)if(top[i]==i)SEGM::build(hrt[i],1,dfn[bot[i]]-dfn[i]+1);
    for(int x=1;x<=n;++x){
        if(G[x].size()>1){
            int cnt=0;
            for(auto y:G[x])if(y!=hson[x])lid[y]=++cnt;
            SEGP::build(lrt[x],1,cnt);
        }
    }
    for(int i=1;i<=n;++i){
        int x=ord[i-1];
        add(&c[x].val,&v[x],1);
        c[x].cnt=1;
        Mult(d[x].a[1][0],c[x],SEGP::b[lrt[x]]);
        SEGM::upd(hrt[top[x]],dfn[x]-dfn[top[x]]+1,d[x],1,dfn[bot[top[x]]]-dfn[top[x]]+1);
        int y;
        while((y=top[x])!=1){
            assign(ptmp1,SEGM::t[hrt[y]].a[0][0]);
            assign(ptmp2,SEGM::t[hrt[y]].a[1][0]);
            Add(ptmp3,ptmp1,ptmp2);
            x=fa[y];
            SEGP::upd(lrt[x],lid[y],ptmp3,ptmp1,1,G[x].size()-1);
            assign(d[x].a[0][0],SEGP::a[lrt[x]]);
            assign(d[x].a[0][1],SEGP::a[lrt[x]]);
            Mult(d[x].a[1][0],c[x],SEGP::b[lrt[x]]);
            SEGM::upd(hrt[top[x]],dfn[x]-dfn[top[x]]+1,d[x],1,dfn[bot[top[x]]]-dfn[top[x]]+1);
        }
        x=ord[i-1];
        add(&oans[x],&SEGM::t[hrt[1]].a[0][0].val,1);
        add(&oans[x],&SEGM::t[hrt[1]].a[1][0].val,1);
    }
    for(int i=n;i>=2;--i)add(&oans[ord[i-1]],&oans[ord[i-2]],P-1);
    for(int i=1;i<=n;++i)assign(v[i],oans[i]);
    reverse(seq,seq+scnt);
    cerr<<scnt<<endl;
    for(int i=0;i<scnt;++i){
        Op x=seq[i];
        if(x.v<0)*x.y=(*x.y+(ll)*x.x*(-x.v))%P,*x.x=0;
        else *x.y=(*x.y+(ll)*x.x*x.v)%P;
    }
    for(int i=1;i<=n;++i)printf("%d ",v[i]);puts("");
}
}
bool en_memory;
signed main(){
    bg_clock=chrono::high_resolution_clock::now();
    GENSOKYO::gskinit();
    int T=1;//cin>>T;
    while(T--)GENSOKYO::main();
    debugTime();
    double memory_used=(&en_memory-&bg_memory)/1024.0/1024;
    cerr<<"Memory: "<<memory_used<<"MB"<<endl;
    return 0;
}

Step 2

操作序列是 O(n\log^2 n) 的,远远超出空间限制,甚至无法编译(一个指针大小 64 位)。

考虑全局平衡二叉树,但是一个点的轻儿子平衡树不行。笔者不会 Top tree 但是似乎 toptree 可以通过 Rake 操作平衡做到这一点。

怎么办?观察这个操作,转置的话,其实不需要全记,倒着修改每一个点,每一段记录然后分别转置就好了。

但是这样的话就要记录每一个版本了怎么办?可以每次手动回退版本。这也是容易的具体可以看看代码。

record

#include<bits/stdc++.h>
using namespace std;
bool bg_memory;
chrono::_V2::system_clock::time_point bg_clock,en_clock;
void debugTime(){
    en_clock=chrono::high_resolution_clock::now();
    auto duration_clock=chrono::duration_cast<chrono::microseconds>(en_clock-bg_clock);
    double duration_count=duration_clock.count()*0.001;
    cerr<<"Time:"<<duration_count<<"ms"<<endl;
}
namespace GENSOKYO{
template<typename T>
void read(T &a){
    char c;a=0;int f=1;
    while(!isdigit(c=getchar()))if(c=='-')f=-1;
    do a=a*10+c-'0';
    while(isdigit(c=getchar()));
    a*=f;
}
template<typename T>
void write(T a){
    if(a<0)putchar('-'),a=-a;
    if(a>=10)write(a/10);
    putchar('0'+a%10);
}
char GC(){
    char c=getchar();
    while(c<=32)c=getchar();
    return c;
}
template<typename T1,typename T2>
void chmin(T1 &x,T2 y){if(x>y)x=y;}
template<typename T1,typename T2>
void chmax(T1 &x,T2 y){if(x<y)x=y;}
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef unsigned int ui;
typedef pair<int,int> PII;
typedef pair<ll,int> PLI;
typedef __int128 lll;
mt19937 rng(chrono::system_clock::now().time_since_epoch().count());
int RRand(int n){return (ull)rng()*n>>32;}
int RRand(int l,int r){return l+RRand(r-l+1);}
void gskinit(){
}
const int MAXN=300010;
const int P=998244353;
int n,fa[MAXN];
vector<int> G[MAXN];
int v[MAXN];
struct Op{
    int *x,*y,v;//x+=y*v;
    bool type;
    Op(){}
    Op(int *_x,int *_y,int _v):x(_x),y(_y){type=_v<0;v=_v<0?-_v:_v;}
};
struct Pr{
    int val,cnt;
    Pr(){cnt=1;}
};
struct Mat{
    Pr a[2][2];
    Mat(){a[1][0].cnt=a[1][1].cnt=0;}
};
Op seq[1000010];int scnt;
bool record;
void add(int *x,int *y,int v){
    if(!record)return;
    seq[scnt++]=Op(x,y,v);
}
void assign(int &A,int &B,int v=1){
    if(!record)return;
    seq[scnt++]=Op(&A,&B,v==0?-P:-v);
    assert(seq[scnt-1].v>=0);
}
void assign(Pr &A,Pr &B){
    A.cnt=B.cnt;
    assign(A.val,B.val);
}
void assign(Mat &A,Mat &B){
    for(int i=0;i<2;++i)
        for(int j=0;j<2;++j)
            assign(A.a[i][j],B.a[i][j]);
}
void Add(Pr &A,Pr &B,Pr &C){
    assign(A.val,B.val,1);
    add(&A.val,&C.val,1);
    A.cnt=(B.cnt+C.cnt)%P;
}
void Mult(Pr &A,Pr &B,Pr &C){
    assign(A.val,B.val,C.cnt);
    add(&A.val,&C.val,B.cnt);
    A.cnt=(ll)B.cnt*C.cnt%P;
}
void Mult(Mat &A,Mat &B,Mat &C){
    for(int i=0;i<2;++i)
        for(int j=0;j<2;++j){
            assign(A.a[i][j].val,B.a[i][0].val,C.a[0][j].cnt);
            add(&A.a[i][j].val,&C.a[0][j].val,B.a[i][0].cnt);
            add(&A.a[i][j].val,&B.a[i][1].val,C.a[1][j].cnt);
            add(&A.a[i][j].val,&C.a[1][j].val,B.a[i][1].cnt);
            A.a[i][j].cnt=((ll)B.a[i][0].cnt*C.a[0][j].cnt+(ll)B.a[i][1].cnt*C.a[1][j].cnt)%P;
        }
}
Pr ptmp1,ptmp2,ptmp3;
namespace SEGM{
int sgtot;
Mat t[MAXN<<2];
int ch[MAXN<<2][2];
#define mid (L+R>>1)
void build(int &x,int L,int R){
    if(!x)x=++sgtot;
    if(L==R){
    }else{
        build(ch[x][0],L,mid);
        build(ch[x][1],mid+1,R);
    }
}
void pushup(int x){
    Mult(t[x],t[ch[x][0]],t[ch[x][1]]);
}
void upd(int x,int pos,Mat &v,int L,int R){
    if(L==R){
        assign(t[x],v);
    }else{
        if(pos<=mid)upd(ch[x][0],pos,v,L,mid);
        else upd(ch[x][1],pos,v,mid+1,R);
        pushup(x);
    }
}
#undef mid
}
namespace SEGP{
Pr a[MAXN<<2],b[MAXN<<2];int sgtot;
int ch[MAXN<<2][2];
// a: 0+1 ; b: 0
#define mid (L+R>>1)
void build(int &x,int L,int R){
    if(!x)x=++sgtot;
    if(L==R){
    }else{
        build(ch[x][0],L,mid);
        build(ch[x][1],mid+1,R);
    }
}
void pushup(int x){
    Mult(a[x],a[ch[x][0]],a[ch[x][1]]);
    Mult(b[x],b[ch[x][0]],b[ch[x][1]]);
}
void upd(int x,int pos,Pr &A,Pr &B,int L,int R){
    if(L==R){
        assign(a[x],A);
        assign(b[x],B);
    }else{
        if(pos<=mid)upd(ch[x][0],pos,A,B,L,mid);
        else upd(ch[x][1],pos,A,B,mid+1,R);
        pushup(x);
    }
}
#undef mid
}
int siz[MAXN],hson[MAXN],top[MAXN],dfn[MAXN],fdfn[MAXN],bot[MAXN],dfc;
int lid[MAXN];//light son id
int hrt[MAXN],lrt[MAXN];// heavy chain segT ; light son segT
void dfs1(int x){
    siz[x]=1;hson[x]=0;
    for(int y:G[x]){
        dfs1(y);
        if(siz[y]>siz[hson[x]])hson[x]=y;
        siz[x]+=siz[y];
    }
}
void dfs2(int x,int topf){
    fdfn[dfn[x]=++dfc]=x;
    top[x]=topf;
    bot[top[x]]=x;
    if(hson[x])dfs2(hson[x],topf);
    for(int y:G[x])if(y!=hson[x]){
        dfs2(y,y);
    }
}
Pr c[MAXN];// the coefficient for vertex x
Mat d[MAXN];// the matrix for vertex x
int oans[MAXN];
void execute(){
    for(int i=scnt-1;~i;--i){
        *seq[i].y=(*seq[i].y+(ll)*seq[i].x*seq[i].v)%P;
        if(seq[i].type)*seq[i].x=0;
    }
}
int _0;
void main(){
    read(n);
    for(int i=2;i<=n;++i){
        read(fa[i]);
        G[fa[i]].emplace_back(i);
    }
    for(int i=1;i<=n;++i)read(v[i]),c[i].cnt=0;
    vector<int> ord(n);
    for(int i=0;i<n;++i)ord[i]=i+1;
    sort(ord.begin(),ord.end(),[&](int x,int y){return v[x]<v[y];});
    dfs1(1),dfs2(1,1);
    for(int i=1;i<=n;++i)if(top[i]==i)SEGM::build(hrt[i],1,dfn[bot[i]]-dfn[i]+1);
    for(int x=1;x<=n;++x){
        if(G[x].size()>1){
            int cnt=0;
            for(auto y:G[x])if(y!=hson[x])lid[y]=++cnt;
            SEGP::build(lrt[x],1,cnt);
        }
    }
    record=0;
    for(int i=1;i<=n;++i){
        int x=ord[i-1];
        add(&c[x].val,&v[x],1);
        c[x].cnt=1;
        Mult(d[x].a[1][0],c[x],SEGP::b[lrt[x]]);
        SEGM::upd(hrt[top[x]],dfn[x]-dfn[top[x]]+1,d[x],1,dfn[bot[top[x]]]-dfn[top[x]]+1);
        int y;
        while((y=top[x])!=1){
            assign(ptmp1,SEGM::t[hrt[y]].a[0][0]);
            assign(ptmp2,SEGM::t[hrt[y]].a[1][0]);
            Add(ptmp3,ptmp1,ptmp2);
            x=fa[y];
            SEGP::upd(lrt[x],lid[y],ptmp3,ptmp1,1,G[x].size()-1);
            assign(d[x].a[0][0],SEGP::a[lrt[x]]);
            assign(d[x].a[0][1],SEGP::a[lrt[x]]);
            Mult(d[x].a[1][0],c[x],SEGP::b[lrt[x]]);
            SEGM::upd(hrt[top[x]],dfn[x]-dfn[top[x]]+1,d[x],1,dfn[bot[top[x]]]-dfn[top[x]]+1);
        }
        x=ord[i-1];
        add(&oans[x],&SEGM::t[hrt[1]].a[0][0].val,1);
        add(&oans[x],&SEGM::t[hrt[1]].a[1][0].val,1);
    }
    record=1;
    scnt=0;
    for(int i=n;i>=2;--i)add(&oans[ord[i-1]],&oans[ord[i-2]],P-1);
    for(int i=1;i<=n;++i)assign(v[i],oans[i]);
    execute();
    scnt=0;
    for(int i=n,x;i>=1;--i){
        auto process=[&](int val){
            x=ord[i-1];
            add(&c[x].val,&v[x],1);
            c[x].cnt=val;
            Mult(d[x].a[1][0],c[x],SEGP::b[lrt[x]]);
            SEGM::upd(hrt[top[x]],dfn[x]-dfn[top[x]]+1,d[x],1,dfn[bot[top[x]]]-dfn[top[x]]+1);
            int y;
            while((y=top[x])!=1){
                assign(ptmp1,SEGM::t[hrt[y]].a[0][0]);
                assign(ptmp2,SEGM::t[hrt[y]].a[1][0]);
                Add(ptmp3,ptmp1,ptmp2);
                x=fa[y];
                SEGP::upd(lrt[x],lid[y],ptmp3,ptmp1,1,G[x].size()-1);
                assign(d[x].a[0][0],SEGP::a[lrt[x]]);
                assign(d[x].a[0][1],SEGP::a[lrt[x]]);
                Mult(d[x].a[1][0],c[x],SEGP::b[lrt[x]]);
                SEGM::upd(hrt[top[x]],dfn[x]-dfn[top[x]]+1,d[x],1,dfn[bot[top[x]]]-dfn[top[x]]+1);
            }
            x=ord[i-1];
            add(&oans[x],&SEGM::t[hrt[1]].a[0][0].val,1);
            add(&oans[x],&SEGM::t[hrt[1]].a[1][0].val,1);
        };
        record=0;
        process(0);
        record=1;
        process(1);
        execute();
        record=0,scnt=0;
        process(0);
    }
    for(int i=1;i<=n;++i)printf("%d ",v[i]);puts("");
}
}
bool en_memory;
signed main(){
    bg_clock=chrono::high_resolution_clock::now();
    GENSOKYO::gskinit();
    int T=1;//cin>>T;
    while(T--)GENSOKYO::main();
    debugTime();
    double memory_used=(&en_memory-&bg_memory)/1024.0/1024;
    cerr<<"Memory: "<<memory_used<<"MB"<<endl;
    return 0;
}

Step 3

卡常!

首先删除线段树中动态开点的 &x 引用。

然后开 inline

展开矩阵乘法。

使用 c++23。

然后就可以通过!

record

#include<bits/stdc++.h>
using namespace std;
bool bg_memory;
chrono::_V2::system_clock::time_point bg_clock,en_clock;
void debugTime(){
    en_clock=chrono::high_resolution_clock::now();
    auto duration_clock=chrono::duration_cast<chrono::microseconds>(en_clock-bg_clock);
    double duration_count=duration_clock.count()*0.001;
    cerr<<"Time:"<<duration_count<<"ms"<<endl;
}
namespace GENSOKYO{
template<typename T>
void read(T &a){
    char c;a=0;int f=1;
    while(!isdigit(c=getchar()))if(c=='-')f=-1;
    do a=a*10+c-'0';
    while(isdigit(c=getchar()));
    a*=f;
}
template<typename T>
void write(T a){
    if(a<0)putchar('-'),a=-a;
    if(a>=10)write(a/10);
    putchar('0'+a%10);
}
char GC(){
    char c=getchar();
    while(c<=32)c=getchar();
    return c;
}
template<typename T1,typename T2>
void chmin(T1 &x,T2 y){if(x>y)x=y;}
template<typename T1,typename T2>
void chmax(T1 &x,T2 y){if(x<y)x=y;}
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef unsigned int ui;
typedef pair<int,int> PII;
typedef pair<ll,int> PLI;
typedef __int128 lll;
mt19937 rng(chrono::system_clock::now().time_since_epoch().count());
int RRand(int n){return (ull)rng()*n>>32;}
int RRand(int l,int r){return l+RRand(r-l+1);}
void gskinit(){
}
const int MAXN=300010;
const int P=998244353;
int n,fa[MAXN];
vector<int> G[MAXN];
int v[MAXN];
struct Op{
    int *x,*y,v;//x+=y*v;
    bool type;
    Op(){}
    Op(int *_x,int *_y,int _v):x(_x),y(_y){type=_v<0;v=_v<0?-_v:_v;}
};
struct Pr{
    int val,cnt;
    Pr(){cnt=1;}
};
struct Mat{
    Pr a[2][2];
    Mat(){a[1][0].cnt=a[1][1].cnt=0;}
};
Op seq[2010];int scnt;
bool record;
inline void add(int *x,int *y,int v){
    if(!record)return;
    seq[scnt++]=Op(x,y,v);
}
inline void assign(int &A,int &B,int v=1){
    if(!record)return;
    seq[scnt++]=Op(&A,&B,v==0?-P:-v);
    assert(seq[scnt-1].v>=0);
}
inline void assign(Pr &A,Pr &B){
    A.cnt=B.cnt;
    if(!record)return;
    assign(A.val,B.val);
}
inline void assign(Mat &A,Mat &B){
    for(int i=0;i<2;++i)
        for(int j=0;j<2;++j)
            assign(A.a[i][j],B.a[i][j]);
}
inline void Add(Pr &A,Pr &B,Pr &C){
    A.cnt=(B.cnt+C.cnt)%P;
    if(!record)return;
    assign(A.val,B.val,1);
    add(&A.val,&C.val,1);
}
inline void Mult(Pr &A,Pr &B,Pr &C){
    A.cnt=(ll)B.cnt*C.cnt%P;
    if(!record)return;
    assign(A.val,B.val,C.cnt);
    add(&A.val,&C.val,B.cnt);
}
inline void Mult(Mat &A,Mat &B,Mat &C){
    A.a[0][0].cnt=((ll)B.a[0][0].cnt*C.a[0][0].cnt+(ll)B.a[0][1].cnt*C.a[1][0].cnt)%P;
    A.a[0][1].cnt=((ll)B.a[0][0].cnt*C.a[0][1].cnt+(ll)B.a[0][1].cnt*C.a[1][1].cnt)%P;
    A.a[1][0].cnt=((ll)B.a[1][0].cnt*C.a[0][0].cnt+(ll)B.a[1][1].cnt*C.a[1][0].cnt)%P;
    A.a[1][1].cnt=((ll)B.a[1][0].cnt*C.a[0][1].cnt+(ll)B.a[1][1].cnt*C.a[1][1].cnt)%P;
    if(!record)return;
    #define MAT_MUL_2X2(Aij, Bi0, Bi1, C0j, C1j)      \
        {                                        \
            assign((Aij).val, (Bi0).val, (C0j).cnt);\
            add(&(Aij).val, &(C0j).val, (Bi0).cnt);\
            add(&(Aij).val, &(Bi1).val, (C1j).cnt);\
            add(&(Aij).val, &(C1j).val, (Bi1).cnt);\
        }
    MAT_MUL_2X2(A.a[0][0],B.a[0][0], B.a[0][1],C.a[0][0], C.a[1][0]);
    MAT_MUL_2X2(A.a[0][1],B.a[0][0], B.a[0][1],C.a[0][1], C.a[1][1]);
    MAT_MUL_2X2(A.a[1][0],B.a[1][0], B.a[1][1],C.a[0][0], C.a[1][0]);
    MAT_MUL_2X2(A.a[1][1],B.a[1][0], B.a[1][1],C.a[0][1], C.a[1][1]);
}
Pr ptmp1,ptmp2,ptmp3;
namespace SEGM{
int sgtot;
Mat t[MAXN<<2];
int ch[MAXN<<2][2];
#define mid (L+R>>1)
void build(int &x,int L,int R){
    if(!x)x=++sgtot;
    if(L==R){
    }else{
        build(ch[x][0],L,mid);
        build(ch[x][1],mid+1,R);
    }
}
void pushup(int x){
    Mult(t[x],t[ch[x][0]],t[ch[x][1]]);
}
void upd(int x,int pos,Mat &v,int L,int R){
    if(L==R){
        assign(t[x],v);
    }else{
        if(pos<=mid)upd(ch[x][0],pos,v,L,mid);
        else upd(ch[x][1],pos,v,mid+1,R);
        pushup(x);
    }
}
#undef mid
}
namespace SEGP{
Pr a[MAXN<<2],b[MAXN<<2];int sgtot;
int ch[MAXN<<2][2];
// a: 0+1 ; b: 0
#define mid (L+R>>1)
void build(int &x,int L,int R){
    if(!x)x=++sgtot;
    if(L==R){
    }else{
        build(ch[x][0],L,mid);
        build(ch[x][1],mid+1,R);
    }
}
void pushup(int x){
    Mult(a[x],a[ch[x][0]],a[ch[x][1]]);
    Mult(b[x],b[ch[x][0]],b[ch[x][1]]);
}
void upd(int x,int pos,Pr &A,Pr &B,int L,int R){
    if(L==R){
        assign(a[x],A);
        assign(b[x],B);
    }else{
        if(pos<=mid)upd(ch[x][0],pos,A,B,L,mid);
        else upd(ch[x][1],pos,A,B,mid+1,R);
        pushup(x);
    }
}
#undef mid
}
int siz[MAXN],hson[MAXN],top[MAXN],dfn[MAXN],fdfn[MAXN],bot[MAXN],dfc;
int lid[MAXN];//light son id
int hrt[MAXN],lrt[MAXN];// heavy chain segT ; light son segT
void dfs1(int x){
    siz[x]=1;hson[x]=0;
    for(int y:G[x]){
        dfs1(y);
        if(siz[y]>siz[hson[x]])hson[x]=y;
        siz[x]+=siz[y];
    }
}
void dfs2(int x,int topf){
    fdfn[dfn[x]=++dfc]=x;
    top[x]=topf;
    bot[top[x]]=x;
    if(hson[x])dfs2(hson[x],topf);
    for(int y:G[x])if(y!=hson[x]){
        dfs2(y,y);
    }
}
Pr c[MAXN];// the coefficient for vertex x
Mat d[MAXN];// the matrix for vertex x
int oans[MAXN];
void execute(){
    for(int i=scnt-1;~i;--i){
        *seq[i].y=(*seq[i].y+(ll)*seq[i].x*seq[i].v)%P;
        if(seq[i].type)*seq[i].x=0;
    }
}
int _0;
void main(){
    read(n);
    for(int i=2;i<=n;++i){
        read(fa[i]);
        G[fa[i]].emplace_back(i);
    }
    for(int i=1;i<=n;++i)read(v[i]),c[i].cnt=0;
    vector<int> ord(n);
    for(int i=0;i<n;++i)ord[i]=i+1;
    sort(ord.begin(),ord.end(),[&](int x,int y){return v[x]<v[y];});
    dfs1(1),dfs2(1,1);
    for(int i=1;i<=n;++i)if(top[i]==i)SEGM::build(hrt[i],1,dfn[bot[i]]-dfn[i]+1);
    for(int x=1;x<=n;++x){
        if(G[x].size()>1){
            int cnt=0;
            for(auto y:G[x])if(y!=hson[x])lid[y]=++cnt;
            SEGP::build(lrt[x],1,cnt);
        }
    }
    record=0;
    for(int i=1;i<=n;++i){
        int x=ord[i-1];
        add(&c[x].val,&v[x],1);
        c[x].cnt=1;
        Mult(d[x].a[1][0],c[x],SEGP::b[lrt[x]]);
        SEGM::upd(hrt[top[x]],dfn[x]-dfn[top[x]]+1,d[x],1,dfn[bot[top[x]]]-dfn[top[x]]+1);
        int y;
        while((y=top[x])!=1){
            assign(ptmp1,SEGM::t[hrt[y]].a[0][0]);
            assign(ptmp2,SEGM::t[hrt[y]].a[1][0]);
            Add(ptmp3,ptmp1,ptmp2);
            x=fa[y];
            SEGP::upd(lrt[x],lid[y],ptmp3,ptmp1,1,G[x].size()-1);
            assign(d[x].a[0][0],SEGP::a[lrt[x]]);
            assign(d[x].a[0][1],SEGP::a[lrt[x]]);
            Mult(d[x].a[1][0],c[x],SEGP::b[lrt[x]]);
            SEGM::upd(hrt[top[x]],dfn[x]-dfn[top[x]]+1,d[x],1,dfn[bot[top[x]]]-dfn[top[x]]+1);
        }
        x=ord[i-1];
        add(&oans[x],&SEGM::t[hrt[1]].a[0][0].val,1);
        add(&oans[x],&SEGM::t[hrt[1]].a[1][0].val,1);
    }
    for(int i=1;i<=n;++i)oans[i]=v[i],v[i]=0;
    for(int i=1;i<=n-1;++i)oans[ord[i-1]]=(oans[ord[i-1]]+(ll)oans[ord[i]]*(P-1))%P;
    for(int i=n,x;i>=1;--i){
        auto process=[&](int val){
            x=ord[i-1];
            add(&c[x].val,&v[x],1);
            c[x].cnt=val;
            Mult(d[x].a[1][0],c[x],SEGP::b[lrt[x]]);
            SEGM::upd(hrt[top[x]],dfn[x]-dfn[top[x]]+1,d[x],1,dfn[bot[top[x]]]-dfn[top[x]]+1);
            int y;
            while((y=top[x])!=1){
                assign(ptmp1,SEGM::t[hrt[y]].a[0][0]);
                assign(ptmp2,SEGM::t[hrt[y]].a[1][0]);
                Add(ptmp3,ptmp1,ptmp2);
                x=fa[y];
                SEGP::upd(lrt[x],lid[y],ptmp3,ptmp1,1,G[x].size()-1);
                assign(d[x].a[0][0],SEGP::a[lrt[x]]);
                assign(d[x].a[0][1],SEGP::a[lrt[x]]);
                Mult(d[x].a[1][0],c[x],SEGP::b[lrt[x]]);
                SEGM::upd(hrt[top[x]],dfn[x]-dfn[top[x]]+1,d[x],1,dfn[bot[top[x]]]-dfn[top[x]]+1);
            }
            x=ord[i-1];
            add(&oans[x],&SEGM::t[hrt[1]].a[0][0].val,1);
            add(&oans[x],&SEGM::t[hrt[1]].a[1][0].val,1);
        };
        record=0;
        process(0);
        scnt=0;record=1;
        process(1);
        execute();
        record=0;
        process(0);
    }
    for(int i=1;i<=n;++i)write(v[i]),putchar(' ');puts("");
}
}
bool en_memory;
signed main(){
    bg_clock=chrono::high_resolution_clock::now();
    GENSOKYO::gskinit();
    int T=1;//cin>>T;
    while(T--)GENSOKYO::main();
    debugTime();
    double memory_used=(&en_memory-&bg_memory)/1024.0/1024;
    cerr<<"Memory: "<<memory_used<<"MB"<<endl;
    return 0;
}

拒绝 Top tree,从每一道题开始。