蒟蒻第一天学C艹,简单树链剖分题目求调STO
查看原帖
蒟蒻第一天学C艹,简单树链剖分题目求调STO
1006027
Skadi_H楼主2024/5/9 09:59

用的是 树链剖分&线段树 加delta=dep^k-(dep-1)^k

样例过了,测试点只过了 #9,#10

QAQ

#include <bits/stdc++.h>
using namespace std;
const int mod=998244353;
struct edge
{
	long long v,nxt;
}e[100005];
struct stree
{
	long long l,r,val,tag,dval;
}t[200005];
struct quest
{
	long long x,pos,id;
	bool operator<(const quest &t)const
	{
		return x<t.x;
	}
}q[50005];
long long n,Q,k,u,pos,cnt,cur;
long long head[50005],d[50005],ans[50005];
long long dep[50005],siz[50005],fa[50005],son[50005];
long long dfn[50005],p[50005],top[50005];
long long ksm(long long a,long long b)
{
	long long res=1;
	while(b)
	{
		if(b&1)
			res=res*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return res;
}
void addedge(int u,int v)
{
	e[++pos]={v,head[u]};
	head[u]=pos;
}
void dfs1(int u,int f)
{
	dep[u]=dep[f]+1;
	siz[u]=1;
	fa[u]=f;
	int maxson=0;
	for(int i=head[u];i;i=e[i].nxt)
	{
		int v=e[i].v;
		if(v==f)
			continue;
		dfs1(v,u);
		siz[u]+=siz[v];
		if(siz[v]>maxson)
		{
			maxson=siz[v];
			son[u]=v;
		}
	}
}
void dfs2(int u,int t)
{
	dfn[u]=++cnt;
	p[cnt]=u;
	top[u]=t;
	if(!son[u])
		return;
	dfs2(son[u],t);
	for(int i=head[u];i;i=e[i].nxt)
	{
		int v=e[i].v;
		if(v==fa[u]||v==son[u])
			continue;
		dfs2(v,v);
	}
}
void pushup(int idx)
{
	t[idx].val=(t[2*idx].val+t[2*idx+1].val)%mod;
	t[idx].dval=(t[2*idx].dval+t[2*idx+1].dval)%mod;
}
void add(int idx,long long val)
{
	t[idx].val=(t[idx].val+val*t[idx].dval)%mod;
	t[idx].tag=(t[idx].tag+val)%mod;
}
void pushdown(int idx)
{
	if(t[idx].tag)
	{
		add(2*idx,t[idx].tag);
		add(2*idx+1,t[idx].tag);
		t[idx].tag=0;
	}
}
void build(int idx,int l,int r)
{
	t[idx].l=l,t[idx].r=r;
	if(l==r)
	{
		t[idx].dval=d[dep[p[l]]];
		return;
	}
	int mid=l+r>>1;
	build(2*idx,l,mid);
	build(2*idx+1,mid+1,r);
	pushup(idx);
}
void update(int idx,int l,int r)
{
	if(t[idx].r<l||t[idx].l>r)
		return;
	if(l<=t[idx].l&&t[idx].r<=r)
	{
		add(idx,1);
		return;
	}
	pushdown(idx);
	int mid=t[idx].l+t[idx].r>>1;
	if(l<=mid)
		update(2*idx,l,r);
	if(mid+1<=r)
		update(2*idx+1,l,r);
	pushup(idx);
}
long long query(int idx,int l,int r)
{
	if(t[idx].r<l||t[idx].l>r)
		return 0;
	if(l<=t[idx].l&&t[idx].r<=r)
		return t[idx].val;
	pushdown(idx);
	int mid=t[idx].l+t[idx].r>>1;
	long long res=0;
	if(l<=mid)
		res=(res+query(2*idx,l,r))%mod;
	if(mid+1<=r)
		res=(res+query(2*idx+1,l,r))%mod;
	return res;
}
void updatepath(int u,int v)
{
	while(top[u]!=top[v])
	{
		if(dep[top[u]]<dep[top[v]])
			swap(u,v);
		update(1,dfn[top[u]],dfn[u]);
		u=fa[top[u]];
	}
	if(dep[u]>dep[v])
		swap(u,v);
	update(1,dfn[u],dfn[v]);
}
long long querypath(int u,int v)
{
	long long res=0;
	while(top[u]!=top[v])
	{
		if(dep[top[u]]<dep[top[v]])
			swap(u,v);
		res=(res+query(1,dfn[top[u]],dfn[u]))%mod;
		u=fa[top[u]];
	}
	if(dep[u]>dep[v])
		swap(u,v);
	res=(res+query(1,dfn[u],dfn[v]))%mod;
	return res;
}
void init(int n,long long k)
{
	for(int i=1;i<=n;i++)
	{
		d[i]=ksm(i,k);
	}
	for(int i=n;i>=1;i--)
	{
		d[i]=((d[i]-d[i-1])%mod+mod)%mod;
	}
}
signed main(){
	std::ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	cin>>n>>Q>>k;
	init(n,k);
	for(int i=2;i<=n;i++)
	{
		cin>>u;
		addedge(i,u);
		addedge(u,i);
	}
	dfs1(1,0);
	dfs2(1,1);
	build(1,1,n);
	for(int i=1;i<=Q;i++)
	{
		cin>>q[i].x>>q[i].pos;
		q[i].id=i; 
	}
	sort(q+1,q+Q+1);
	cur=1;
	for(int i=1;i<=n;i++)
	{
		updatepath(1,i);
		while(cur<=Q&&q[cur].x<=i)
		{
			ans[q[cur].id]=querypath(1,q[i].pos);
			cur++;
		}
	}
	for(int i=1;i<=Q;i++)
	{
		cout<<ans[i]<<"\n";
	}
	return 0;
}
//Skadi_H
2024/5/9 09:59
加载中...