上道题是这道题的递归题。
如果明白上道题的处理方式,这道题就差不多了 。
唯一的难点在于k次方,如何维护?
如果我们仍然将1到某个点权值都+1,还要满足这对该点子树贡献是该点深度的k次方。
我们可以继续使用差分思想。将第i个点赋一个加权权值为其深度的k次方减去(该点深度-1)的k次方。
然后就可以继续快乐的维护了。
#include<bits/stdc++.h>
using namespace std;
#define in read()
#define int long long
int in{
int cnt=0,f=1;char ch=0;
while(!isdigit(ch)){
ch=getchar();if(ch=='-')f=-1;
}
while(isdigit(ch)){
cnt=cnt*10+ch-48;
ch=getchar();
}return cnt*f;
}
const int mod=998244353;
struct node{
int l,r,a,b,tag,sum;
}t[200003];
struct bili{
int belong,pos,flag,z;
}que[200003];int ins;
int mi[200003],ans[200003];
int n,q,k;
int first[200003],nxt[200003],to[200003],tot,cnt;
int id[200003],dep[200003],pre[200003],son[200003],fa[200003],top[200003],size[200003];
int ksm(int x,int y){
int sum=1;
while(y){
if(y&1)sum=sum*x%mod;x=x*x%mod;y>>=1;
}return sum;
}
void dfs1(int u,int faa){
size[u]=1;fa[u]=faa;dep[u]=dep[faa]+1;
for(int i=first[u];i;i=nxt[i]){
int v=to[i];if(v==faa)continue;
dfs1(v,u);size[u]+=size[v];if(size[v]>size[son[u]])son[u]=v;
}
}
void dfs2(int u,int tp){
id[u]=++cnt;pre[cnt]=u;top[u]=tp;
if(son[u])dfs2(son[u],tp);
for(int i=first[u];i;i=nxt[i]){
int v=to[i];if(v==fa[u]||v==son[u])continue;dfs2(v,v);
}
}
void add(int a,int b){
nxt[++tot]=first[a];first[a]=tot;to[tot]=b;
}
void pushup(int u){
t[u].b=t[u*2].b+t[u*2+1].b;t[u].b%=mod;
t[u].sum=t[u*2].sum+t[u*2+1].sum;t[u].sum%=mod;
}
void build(int u,int l,int r){
t[u].l=l;t[u].r=r;if(l==r){t[u].b=(mi[dep[pre[l]]]-mi[dep[pre[l]]-1]+mod)%mod;return;}
int mid=(l+r)>>1;build(u*2,l,mid);build(u*2+1,mid+1,r);pushup(u);
}
bool cm(bili a,bili b){return a.pos<b.pos;}
void pushdown(int u){
if(t[u].tag){
int x=t[u].tag;
t[u*2].tag+=x;t[u*2].tag%=mod;t[u*2+1].tag+=x;t[u*2+1].tag%=mod;
t[u*2].sum+=t[u*2].b*x%mod;t[u*2].sum%=mod;t[u*2+1].sum+=t[u*2+1].b*x%mod;t[u*2+1].sum%=mod;
t[u].tag=0;
}
}
void segmo(int u,int ql,int qr){
if(t[u].r<ql||t[u].l>qr)return;
if(ql<=t[u].l&&t[u].r<=qr){t[u].sum=(t[u].sum+t[u].b)%mod;t[u].tag=(t[u].tag+1)%mod;return;}
pushdown(u);segmo(u*2,ql,qr);segmo(u*2+1,ql,qr);pushup(u);
}
void modify(int a,int b){
int x=top[a],y=top[b];
while(x!=y){
if(dep[x]<dep[y])swap(x,y),swap(a,b);
segmo(1,id[x],id[a]);
a=fa[x];x=top[a];
}if(id[a]>id[b])swap(a,b);
segmo(1,id[a],id[b]);
}
int segquery(int u,int ql,int qr){
if(t[u].r<ql||t[u].l>qr)return 0;
if(ql<=t[u].l&&t[u].r<=qr)return t[u].sum;
pushdown(u);return (segquery(u*2,ql,qr)+segquery(u*2+1,ql,qr))%mod;
pushup(u);
}
int query(int a,int b){
int x=top[a],y=top[b],sum=0;
while(x!=y){
if(dep[x]<dep[y])swap(x,y),swap(a,b);
sum=(sum+segquery(1,id[x],id[a]))%mod;
a=fa[x];x=top[a];
}if(id[a]>id[b])swap(a,b);
sum=(sum+segquery(1,id[a],id[b]))%mod;
return sum;
}
void debug1(int u,int l,int r){
cout<<l<<" "<<r<<" "<<t[u].b<<endl;
if(l==r)return;
int mid=(l+r)>>1;debug1(u*2,l,mid);debug1(u*2+1,mid+1,r);
}
void debug2(int u,int l,int r){
cout<<l<<" "<<r<<" "<<t[u].sum<<endl;
if(l==r)return;pushdown(u);
int mid=(l+r)>>1;debug2(u*2,l,mid);debug2(u*2+1,mid+1,r);
}
signed main(){
n=in;q=in;k=in;
mi[0]=1;
for(int i=1;i<=n;i++)mi[i]=ksm(i,k);mi[0]=0;
for(int i=2;i<=n;i++){
int x=in;add(x,i);
}dfs1(1,0);dfs2(1,1);build(1,1,n);int x,y;
// for(int i=1;i<=n;i++)cout<<id[i]<<" ";cout<<endl;
//debug1(1,1,n);
for(int i=1;i<=q;i++){
x=in;y=in;
que[i].pos=x;que[i].z=y;que[i].belong=i;
}sort(que+1,que+q+1,cm);
for(int i=1,ri=1;i<=n;i++){
modify(1,i);//cout<<"#################"<<endl;debug2(1,1,n);
while(que[ri].pos==i){
ans[que[ri].belong]=query(1,que[ri].z);ri++;
}
}
for(int i=1;i<=q;i++)printf("%lld\n",ans[i]);
return 0;
}