Description
给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色
Input
第一行一个数T,表示数据组数 接下来每组数据的第一行三个数n,c,q表示结点个数,颜色数和操作数 接下来一行n-1个数描述2..n的父节点
接下来q行每行三个数a,l,c 若c为0,表示询问a的颜色 否则将距离a不超过l的a的子节点染成c
Output
设当前是第i个操作,y_i为本次询问的答案(若本次操作是一个修改则y_i为0),令z_i=i*y_i,请输出z_1+z_2+…+z_q模10^9+7
Sample Input
1
4 3 7
1 2 2
3 0 0
2 1 3
3 0 0
1 0 2
2 0 0
4 1 1
4 0 0
Sample Output
32
HINT
第1,3,5,7的询问的答案分别为1,3,3,1,所以答案为 1*1+2*0+3*3+4*0+5*3+6*0+7*1=32.
数据范围:
对于100%的数据T<=6,n,m,c<=10^5,
1<=a<=n,0<=l<=n,0<=c<=c
题解
神啊我根本没有想过把他转化成一个二维矩阵的做法
第一维dfs序,第二维深度
于是就转化成了矩阵修改单点查询的问题
可以写二维线段树或者树套树?
不过上kdtree就可以了,写一个可以下传标记的
单点查询的时候向上找出父亲把遗传标记下放,修改的时候记得不要把标记动了。。因为这个调了一下午
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const LL mod=1e9+7;
struct node
{
int lc,rc,d[2],mx[2],mn[2],c,op,f;
bool lazy;
}tr[110000];
void upd(int now)
{
int lc=tr[now].lc,rc=tr[now].rc;
if(lc)for(int i=0;i<=1;i++)tr[now].mx[i]=max(tr[lc].mx[i],tr[now].mx[i]),tr[now].mn[i]=min(tr[lc].mn[i],tr[now].mn[i]);
if(rc)for(int i=0;i<=1;i++)tr[now].mx[i]=max(tr[rc].mx[i],tr[now].mx[i]),tr[now].mn[i]=min(tr[rc].mn[i],tr[now].mn[i]);
}
int belong[110000];
int cmpd;
bool cmp(node n1,node n2){return n1.d[cmpd]<n2.d[cmpd];}
int bt(int l,int r,int f,int d)
{
cmpd=d;
int mid=(l+r)/2;int now=mid;
nth_element(tr+l,tr+mid,tr+r+1,cmp);
tr[now].mx[0]=tr[now].mn[0]=tr[now].d[0];
tr[now].mx[1]=tr[now].mn[1]=tr[now].d[1];
tr[now].f=f;
belong[tr[now].op]=now;
tr[now].lazy=false;
if(l<mid)tr[now].lc=bt(l,mid-1,now,d^1);
if(mid<r)tr[now].rc=bt(mid+1,r,now,d^1);
upd(now);
return now;
}
void lazy(int now)
{
if(tr[now].lazy)
{
int lc=tr[now].lc,rc=tr[now].rc;
if(lc)tr[lc].c=tr[now].c,tr[lc].lazy=true;
if(rc)tr[rc].c=tr[now].c,tr[rc].lazy=true;
tr[now].lazy=false;
}
}
int xx1,yy1,xx2,yy2;//mn mx
void change(int now,int c)
{
if(tr[now].mx[0]<xx1 || tr[now].mn[0]>xx2 || tr[now].mx[1]<yy1 || tr[now].mn[1]>yy2)return ;
if(tr[now].mx[0]<=xx2 && tr[now].mx[1]<=yy2 && tr[now].mn[0]>=xx1 && tr[now].mn[1]>=yy1)
{
tr[now].c=c;tr[now].lazy=true;
return ;
}
if(tr[now].lazy)lazy(now);
if(tr[now].d[0]>=xx1 && tr[now].d[0]<=xx2 && tr[now].d[1]>=yy1 && tr[now].d[1]<=yy2)tr[now].c=c;
int lc=tr[now].lc,rc=tr[now].rc;
if(lc)change(lc,c);
if(rc)change(rc,c);
}
/*int nowx,nowy;
bool check(int now)
{
if(now==0)return false;
if(tr[now].mx[0]<nowx || tr[now].mn[0]>nowx)return false;
if(tr[now].mx[1]<nowy || tr[now].mn[1]>nowy)return false;
return true;
}
int findcol(int now)
{
if(tr[now].d[0]==nowx && tr[now].d[1]==nowy)return tr[now].c;
int lc=tr[now].lc,rc=tr[now].rc;
if(tr[now].lazy)lazy(now);
int tx=-1;
if(lc && check(lc))tx=findcol(lc);
if(tx!=-1)return tx;
if(rc && check(rc))return findcol(rc);
return -1;
}*/
struct edge
{
int x,y,next;
}a[210000];int len,last[110000];
void ins(int x,int y)
{
len++;
a[len].x=x;a[len].y=y;
a[len].next=last[x];last[x]=len;
}
int in[110000],ot[110000],dfn;
int fa[110000],dep[110000];
void pre_tree_node(int x)
{
in[x]=++dfn;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(y!=fa[x])
{
fa[y]=x;
dep[y]=dep[x]+1;
pre_tree_node(y);
}
}
ot[x]=dfn;
}
int tmp[110000],tp;
int findcol(int x)
{
int s=x;tp=0;
while(s!=0)tmp[++tp]=s,s=tr[s].f;
while(tp)lazy(tmp[tp--]);
return tr[x].c;
}
int n,col,q,root;
int main()
{
// freopen("g1.in","r",stdin);
// freopen("g.out","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
LL ans=0;
scanf("%d%d%d",&n,&col,&q);
len=0;memset(last,0,sizeof(last));
for(int i=2;i<=n;i++)
{
int x;scanf("%d",&x);
ins(x,i);
}
fa[1]=0;dep[1]=1;dfn=0;
pre_tree_node(1);
for(int i=1;i<=n;i++)
{
tr[i].d[0]=in[i];tr[i].d[1]=dep[i];
tr[i].lc=tr[i].rc=0;
tr[i].c=1;tr[i].op=i;
}
root=bt(1,n,0,0);
for(int tt=1;tt<=q;tt++)
{
int op,u,x;
scanf("%d%d%d",&u,&x,&op);
if(op==0)
{
int tmp=findcol(belong[u]);
//printf("%d\n",tmp);
ans=(ans+(LL)tmp*tt)%mod;
}
else
{
xx1=in[u];xx2=ot[u];
yy1=dep[u];yy2=dep[u]+x;
change(root,op);
}
}
printf("%lld\n",ans);
}
return 0;
}