一、题目
二、解法
考虑 k-d \text{k-d} k-d树,把每一个点以第一维 d f n dfn dfn序,第二维 d e p dep dep深度插入到二维空间中,修改的话就对第一维在 [ d f i n , d f o u ] [dfin,dfou] [dfin,dfou],第二维在 [ d e p , d e p + l ] [dep,dep+l] [dep,dep+l]中的点打标记,类似于平衡树的修改。
查询要注意一下,虽然只查询一个点,但是由于第二维会有相同权值,单点定位的方法是不行的,我们可以把点看成区间去查,虽然要复杂一些,但是保证了正确性且复杂度不变,我们在查询时顺便释放标记就可以了。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int M = 100005;
const double al = 0.7;
const int jzm = 1e9+7;
int read()
{
int x=0,flag=1;char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int T,n,m,k,opt,ans,rt,cnt,tot,f[M],dfin[M],dfou[M],dep[M];
int Index,mi[M][2],mx[M][2],tag[M],col[M],ls[M],rs[M];
struct node
{
int x[2];
}a[M],v[M];
struct edge
{
int v,next;
edge(int V=0,int N=0) : v(V) , next(N) {}
}e[M];
void up(int x)
{
for(int i=0;i<2;i++)
mi[x][i]=mx[x][i]=v[x].x[i];
if(ls[x])
for(int i=0;i<2;i++)
{
mx[x][i]=max(mx[x][i],mx[ls[x]][i]);
mi[x][i]=min(mi[x][i],mi[ls[x]][i]);
}
if(rs[x])
for(int i=0;i<2;i++)
{
mx[x][i]=max(mx[x][i],mx[rs[x]][i]);
mi[x][i]=min(mi[x][i],mi[rs[x]][i]);
}
}
int cmp(node a,node b)
{
return a.x[opt]<b.x[opt];
}
void build(int &x,int l,int r,int wd)
{
if(l>r) return ;
x=++cnt;
int mid=(l+r)>>1;
opt=wd;
nth_element(a+l,a+mid,a+r+1,cmp);
v[x]=a[mid];col[x]=1;tag[x]=0;
ls[x]=rs[x]=0;
build(ls[x],l,mid-1,wd^1);
build(rs[x],mid+1,r,wd^1);
up(x);
}
int in(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4)
{
return x1<=x3 && x4<=x2 && y1<=y3 && y4<=y2;
}
int out(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4)
{
return x1>x4 || x2<x3 || y1>y4 || y2<y3;
}
void dfs(int u)
{
dfin[u]=++Index;
for(int i=f[u];i;i=e[i].next)
{
int v=e[i].v;
dep[v]=dep[u]+1;
dfs(v);
}
dfou[u]=Index;
a[u].x[0]=dfin[u];
a[u].x[1]=dep[u];
}
void down(int x)
{
if(!tag[x]) return ;
col[ls[x]]=col[rs[x]]=tag[ls[x]]=tag[rs[x]]=tag[x];
tag[x]=0;
}
void modify(int x,int u,int l,int c)
{
if(!x) return ;
if(in(dfin[u],dep[u],dfou[u],dep[u]+l,mi[x][0],mi[x][1],mx[x][0],mx[x][1]))
{
tag[x]=col[x]=c;
return ;
}
if(out(dfin[u],dep[u],dfou[u],dep[u]+l,mi[x][0],mi[x][1],mx[x][0],mx[x][1]))
return ;
if(in(dfin[u],dep[u],dfou[u],dep[u]+l,v[x].x[0],v[x].x[1],v[x].x[0],v[x].x[1]))
col[x]=c;
down(x);
modify(ls[x],u,l,c);
modify(rs[x],u,l,c);
}
int ask(int x,int u)
{
if(!x) return 0;
if(v[x].x[0]==dfin[u]) return col[x];
if(out(dfin[u],dep[u],dfin[u],dep[u],mi[x][0],mi[x][1],mx[x][0],mx[x][1]))
return 0;
down(x);
int t=ask(ls[x],u);
if(t) return t;
return ask(rs[x],u);
}
int main()
{
T=read();
while(T--)
{
tot=cnt=rt=Index=ans=0;memset(f,0,sizeof f);
n=read();m=read();k=read();
for(int j=2;j<=n;j++)
{
int i=read();
e[++tot]=edge(j,f[i]),f[i]=tot;
}
dep[1]=1;
dfs(1);
build(rt,1,n,0);
for(int i=1;i<=k;i++)
{
int u=read(),v=read(),c=read();
if(c)
modify(rt,u,v,c);
else
{
int t=ask(rt,u);
ans=(ans+1ll*i*t%jzm)%jzm;
}
}
printf("%d\n",ans);
}
}