题意:AC通道
题解:
这题有个十分巧妙的解法。
因为有子树修改,而又不是整棵子树的修改,直接上dfs序是不行的。
考虑它每次修改的只有子节点,而且有距离限制,我们想到这是与点的深度有关的问题。
于是我们把树上的点抽象到二维平面上,横坐标为其dfs序,纵坐标为其深度,这样每次的修改就对应一个区域的染色操作,这东西用kdtree可以随便搞,弄个lazytag就可以了。
一堆调试用的代码,所以看起来很长。
#include <bits/stdc++.h>
//#include <conio.h>
using namespace std;
typedef long long ll;
typedef double db;
const int inf=0x3f3f3f3f;
int getint()
{
int f=1,g=0;char c=getchar();
while(c<'0' || c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0' && c<='9')g=(g<<3)+(g<<1)+c-'0',c=getchar();
return f*g;
}
const int maxn=100005;
const int mod=1000000007;
int dim;
int n,m;
struct node{
int d[2];
int max[2];
int min[2];
int l,r;
int tag;
int color;
int& operator [] (const unsigned int& num)
{
return d[num];
}
bool operator < (const node& no)const
{
return d[dim]<no.d[dim];
}
bool operator == (const node& no)const
{
return d[0]==no.d[0] && d[1]==no.d[1];
}
};
node p[maxn];
int root;
struct Kdtree{
node t[maxn];
#define lc t[x].l
#define rc t[x].r
#define ls t[t[x].l]
#define rs t[t[x].r]
void update(int x)
{
t[x].min[0]=t[x].max[0]=t[x][0];
t[x].min[1]=t[x].max[1]=t[x][1];
if(lc)
{
t[x].min[0]=min(t[x].min[0],ls.min[0]);
t[x].max[0]=max(t[x].max[0],ls.max[0]);
t[x].min[1]=min(t[x].min[1],ls.min[1]);
t[x].max[1]=max(t[x].max[1],ls.max[1]);
}
if(rc)
{
t[x].min[0]=min(t[x].min[0],rs.min[0]);
t[x].max[0]=max(t[x].max[0],rs.max[0]);
t[x].min[1]=min(t[x].min[1],rs.min[1]);
t[x].max[1]=max(t[x].max[1],rs.max[1]);
}
}
void push_down(int x)
{
if(!x || !t[x].tag)return;
t[x].color=t[x].tag;
ls.tag=rs.tag=t[x].tag;
t[x].tag=0;
}
#define mid (l+r>>1)
int build(int l,int r,int now)
{
dim=now;
nth_element(p+l,p+mid,p+r+1);
int x=mid;
t[x].color=1;
for(int i=0;i<2;i++)
{
t[x].min[i]=t[x].max[i]=t[x][i]=p[x][i];
}
if(l<mid)lc=build(l,mid-1,now^1);
if(r>mid)rc=build(mid+1,r,now^1);
update(x);
return x;
}
#undef mid
node T1,T2;
int col;
void setcolor(int x)
{
if(!x)return;
push_down(x);
if(t[x].min[0]>T2[0] || t[x].max[0]<T1[0] || t[x].min[1]>T2[1] || t[x].max[1]<T1[1])return;
if(t[x].min[0]>=T1[0] && t[x].max[0]<=T2[0] && t[x].min[1]>=T1[1] && t[x].max[1]<=T2[1])
{
t[x].tag=col;
return;
}
if(t[x][0]>=T1[0] && t[x][0]<=T2[0] && t[x][1]>=T1[1] && t[x][1]<=T2[1])t[x].color=col;
setcolor(lc);setcolor(rc);
}
node T;
int getcolor(int x)
{
push_down(x);
if(T[0]<t[x].min[0] || T[0]>t[x].max[0] || T[1]<t[x].min[1] || T[1]>t[x].max[1])return 0;
if(t[x]==T)return t[x].color;
return getcolor(lc)+getcolor(rc);
}
void set(int x,int y,int xx,int yy,int co)
{
T1[0]=x;T1[1]=y;
T2[0]=xx;T2[1]=yy;
col=co;
setcolor(root);
}
int query(int x,int y)
{
T[0]=x;T[1]=y;
return getcolor(root);
}
void init()
{
memset(t,0,sizeof t);
memset(p,0,sizeof p);
root=0;
}
void run(int x)
{
if(!x)return;
run(lc);
printf("(%d,%d)->(%d,%d):%d(%d)(%d,%d)\n",t[x].min[0],t[x].min[1],t[x].max[0],t[x].max[1],t[x].color,t[x].tag,t[x][0],t[x][1]);
run(rc);
}
#undef lc
#undef rc
#undef ls
#undef rs
}kdtree;
vector<int> g[maxn];
void addedge(int from,int to)
{
g[from].push_back(to);
g[to].push_back(from);
}
int dep[maxn];
int st[maxn];
int ed[maxn];
int ind;
int father[maxn];
void dfs(int x)
{
st[x]=++ind;
for(int i=0;i<g[x].size();i++)
{
int to=g[x][i];
if(father[x]==to)continue;
dep[to]=dep[x]+1;
dfs(to);
}
ed[x]=ind;
}
int main()
{
// freopen("in.txt","r",stdin);
int T=getint();
while(T--)
{
for(int i=0;i<maxn;i++)g[i].clear();
kdtree.init();
ind=0;
n=getint();
int temp=getint();
m=getint();
for(int i=2;i<=n;i++)
{
father[i]=getint();
addedge(i,father[i]);
}
dep[1]=1;
dfs(1);
/*
for(int i=1;i<=n;i++)
{
printf("%d ",st[i]);
}
puts("");
for(int i=1;i<=n;i++)
{
printf("%d ",ed[i]);
}
puts("");
for(int i=1;i<=n;i++)
{
printf("%d ",dep[i]);
}
puts("");
*/
for(int i=1;i<=n;i++)
{
p[i][0]=st[i];
p[i][1]=dep[i];
}
root=kdtree.build(1,n,0);
/*
kdtree.run(root);
puts("");
getch();
*/
int x,y;
int opt;
ll ans=0;
for(int i=1;i<=m;i++)
{
x=getint();
y=getint();
opt=getint();
if(!opt)
{
ll t=kdtree.query(st[x],dep[x]);
//printf("%d\n",t);
ans+=(ll)t*(ll)i;
ans%=mod;
}
else
{
/*
printf("We are painting (%d,%d)->(%d,%d):%d\n",st[x],dep[x],ed[x],dep[x]+y,opt);
getch();
*/
kdtree.set(st[x],dep[x],ed[x],dep[x]+y,opt);
}
/*
kdtree.run(root);
puts("");
getch();
*/
}
printf("%d\n",ans);
}
return 0;
}