树套树或kd-tree
点a的dfs序为一维,另一维是a的层数
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
void up(int &x,const int y){if(x<y)x=y;}
void down(int &x,const int y){if(x>y)x=y;}
int read()
{
char c;int x;
while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
return x;
}
const int maxn = 110000;
const int maxd = 2;
const ll Mod=1e9+7;
int n,m;
struct edge
{
int y,nex;
edge(){}
edge(const int &_y,const int &_nex){y=_y;nex=_nex;}
}a[maxn]; int len,fir[maxn];
void ins(const int &x,const int &y) {a[++len]=edge(y,fir[x]); fir[x]=len;}
struct Kd_tree
{
int c,ci,f,fd,lc,rc,pos[maxd],u[maxd],d[maxd];
}kd[maxn]; int root;
int cmp_d;
bool cmp(const Kd_tree x,const Kd_tree y){return x.pos[cmp_d]<y.pos[cmp_d];}
void push_up(const int &x)
{
const int lc=kd[x].lc,rc=kd[x].rc;
if(lc)
{
for(int i=0;i<maxd;i++)
up(kd[x].u[i],kd[lc].u[i]),down(kd[x].d[i],kd[lc].d[i]);
}
if(rc)
{
for(int i=0;i<maxd;i++)
up(kd[x].u[i],kd[rc].u[i]),down(kd[x].d[i],kd[rc].d[i]);
}
}
int build(const int l,const int r,int D)
{
cmp_d=D; int mid=(l+r)>>1;
std::nth_element(kd+l,kd+mid,kd+r+1,cmp);
kd[mid].fd=0; kd[mid].ci=0;
kd[mid].lc=kd[mid].rc=0;
for(int i=0;i<maxd;i++)
kd[mid].u[i]=kd[mid].d[i]=kd[mid].pos[i];
if(l==r) return mid;
if(l!=mid) kd[mid].lc=build(l,mid-1,!D);
if(mid!=r) kd[mid].rc=build(mid+1,r,!D);
push_up(mid); return mid;
}
int Pu[maxd],Pd[maxd];
int Ci,C;
void upd(const int &x)
{
for(int i=0;i<maxd;i++)
if(Pd[i]>kd[x].u[i]||Pu[i]<kd[x].d[i]) return ;
bool flag=true;
for(int i=0;i<maxd;i++)
if(!(Pd[i]<=kd[x].d[i]&&kd[x].u[i]<=Pu[i])) {flag=false; break;}
if(flag) { kd[x].f=C; kd[x].fd=Ci; return ; }
flag=true;
for(int i=0;i<maxd;i++)
if(!(Pd[i]<=kd[x].pos[i]&&kd[x].pos[i]<=Pu[i])) {flag=false; break;}
if(flag) kd[x].c=C,kd[x].ci=Ci;
if(kd[x].lc) upd(kd[x].lc);
if(kd[x].rc) upd(kd[x].rc);
}
int Ans,Ad;
void Query(const int &x)
{
for(int i=0;i<maxd;i++)
if(Pd[i]>kd[x].u[i]||Pu[i]<kd[x].d[i]) return ;
if(kd[x].fd>Ad) Ans=kd[x].f,Ad=kd[x].fd;
bool flag=true;
for(int i=0;i<maxd;i++)
if(!(Pd[i]<=kd[x].pos[i]&&kd[x].pos[i]<=Pu[i])) {flag=false; break;}
if(flag&&kd[x].ci>Ad) Ans=kd[x].c,Ad=kd[x].ci;
if(kd[x].lc) Query(kd[x].lc);
if(kd[x].rc) Query(kd[x].rc);
}
int siz[maxn],dfn[maxn],dfsid,dep[maxn];
int dfs(const int &x)
{
siz[x]=1;
kd[x].pos[0]=dfn[x]=++dfsid;
kd[x].pos[1]=dep[x];
for(int k=fir[x];k;k=a[k].nex)
{
const int &y=a[k].y; dep[y]=dep[x]+1;
siz[x]+=dfs(y);
}
return siz[x];
}
int main()
{
ll ret=0;
int t=read();
while(t--)
{
memset(fir,0,sizeof fir); len=0;
n=read(); int c=read(); m=read();
for(int i=2;i<=n;i++) ins(read(),i);
dfsid=0; dfs(1);
build(1,n,0); root=(1+n)>>1;
ret=0;
for(int i=1;i<=m;i++)
{
int x=read(),y=read(),c=read();
if(!c)
{
Ans=1,Ad=0;
Pd[0]=Pu[0]=dfn[x];
Pd[1]=Pu[1]=dep[x];
Query(root); ret+=(ll)Ans*(ll)i;
}
else
{
C=c,Ci=i;
Pd[0]=dfn[x],Pu[0]=dfn[x]+siz[x]-1;
Pd[1]=dep[x],Pu[1]=dep[x]+y;
upd(root);
}
}
printf("%lld\n",ret%Mod);
}
return 0;
}