[GX/GZOI2019]旧词(树上差分+树剖+线段树)

考虑k=1的做法:这是一道原题,我还写过题解,其实挺水的,但当时我菜还是看题解的:https://www.cnblogs.com/hfctf0210/p/10187947.html。其实就是树上差分后值为1。

考虑k>1的做法:其实可以再次树上差分,给每个点i赋值v[i]=dep[i]k-dep[i-1]k,然后还是和原来一样开一棵线段树,记录一个val[rt]表示当前节点内区间v值的和,以及sum[rt]表示区间值。修改时打标记,只需要将sum[rt]+=v*val[rt],lazy[rt]+=v即可。树剖一下即可。

#include<bits/stdc++.h>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
typedef pair<int,int>pii;
const int N=,mod=;
int n,Q,k,cnt,dep[N],fa[N],pw[N],sz[N],son[N],top[N],id[N],dfx[N];
int ans[N],sum[N<<],val[N<<],lazy[N<<];
vector<int>G[N];
vector<pii>vec[N];
int qpow(int a,int b)
{
int ret=;
while(b)
{
if(b&)ret=1ll*ret*a%mod;
a=1ll*a*a%mod,b>>=;
}
return ret;
}
void dfs(int u)
{
dep[u]=dep[fa[u]]+,sz[u]=;
for(int i=;i<G[u].size();i++)
if(G[u][i]!=fa[u])
{
dfs(G[u][i]),sz[u]+=sz[G[u][i]];
if(sz[G[u][i]]>sz[son[u]])son[u]=G[u][i];
}
}
void dfs2(int u,int tp)
{
top[u]=tp,id[u]=++cnt,dfx[cnt]=u;
if(son[u])dfs2(son[u],tp);
for(int i=;i<G[u].size();i++)
if(G[u][i]!=fa[u]&&G[u][i]!=son[u])dfs2(G[u][i],G[u][i]);
}
void build(int l,int r,int rt)
{
if(l==r){val[rt]=pw[dep[dfx[l]]];return;}
int mid=l+r>>;
build(lson),build(rson);
val[rt]=(val[rt<<]+val[rt<<|])%mod;
}
void pushdown(int rt)
{
if(!lazy[rt])return;
int v=lazy[rt];lazy[rt]=;
lazy[rt<<]=(lazy[rt<<]+v)%mod,sum[rt<<]=(sum[rt<<]+1ll*v*val[rt<<])%mod;
lazy[rt<<|]=(lazy[rt<<|]+v)%mod,sum[rt<<|]=(sum[rt<<|]+1ll*v*val[rt<<|])%mod;
}
void update(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R){lazy[rt]++,sum[rt]=(sum[rt]+val[rt])%mod;return;}
pushdown(rt);
int mid=l+r>>;
if(L<=mid)update(L,R,lson);
if(R>mid)update(L,R,rson);
sum[rt]=(sum[rt<<]+sum[rt<<|])%mod;
}
void Update(int u)
{
while(top[u]!=)update(id[top[u]],id[u],,n,),u=fa[top[u]];
update(,id[u],,n,);
}
int query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)return sum[rt];
pushdown(rt);
int mid=l+r>>,ret=;
if(L<=mid)ret=(ret+query(L,R,lson))%mod;
if(R>mid)ret=(ret+query(L,R,rson))%mod;
return ret;
}
int Query(int u)
{
int ret=;
while(top[u]!=)ret=(ret+query(id[top[u]],id[u],,n,))%mod,u=fa[top[u]];
ret=(ret+query(,id[u],,n,))%mod;
return ret;
}
int main()
{
scanf("%d%d%d",&n,&Q,&k);
for(int i=;i<=n;i++)pw[i]=(qpow(i,k)-qpow(i-,k)+mod)%mod;
for(int i=;i<=n;i++)scanf("%d",&fa[i]),G[fa[i]].push_back(i);
dfs(),dfs2(,);
build(,n,);
for(int i=,x,y;i<=Q;i++)scanf("%d%d",&x,&y),vec[x].push_back(pii(y,i));
for(int i=;i<=n;i++)
{
Update(i);
for(int j=;j<vec[i].size();j++)ans[vec[i][j].second]=Query(vec[i][j].first);
}
for(int i=;i<=Q;i++)printf("%d\n",ans[i]);
}
上一篇:13-算法训练 P0505


下一篇:本机和虚拟机互联 设置静态IP vmware 虚拟网络 桥接 NAT 仅主机 自定义