4154: [Ipsc2015]Generating Synergy
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 306 Solved: 122
[Submit][Status][Discuss]
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个操作,
yi
为本次询问的答案(若本次操作是一个修改则
yi
为
0
),令
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
因为只有子节点,所以把树上的每个点都对应到二维平面中取。
pos[x]
表示
x
的
染色就是给区间
(L[a],R[a],deep[a],deep[a]+l)
赋值。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
#define Mod 1000000007
const int N=100010;
struct E{int st,en;}aa[N<<1];
int T,n,m,tot,point[N],next[N<<1],pos[N],dfsn,deep[N],root,D,L[N],R[N];
struct S{
int c,de,d[2],mi[2],ma[2],l,r;
int &operator [] (int x){
return d[x];
}
bool operator == (const S &x)const{
return d[0]==x.d[0]&&d[1]==x.d[1];
}
bool operator < (const S &x)const{
return d[D]==x.d[D]?d[D^1]<x.d[D^1]:d[D]<x.d[D];
}
}tr[N],p[N],now;
inline int in(){
int x=0;char ch=getchar();
while(ch<'0'||ch>'9') ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x;
}
inline void add(int x,int y){
next[++tot]=point[x];point[x]=tot;
aa[tot].st=x;aa[tot].en=y;
next[++tot]=point[y];point[y]=tot;
aa[tot].st=y;aa[tot].en=x;
}
inline void dfs(int x,int last){
int i;
L[x]=R[x]=pos[x]=++dfsn;
for(i=point[x];i;i=next[i])
if(aa[i].en!=last){
deep[aa[i].en]=deep[x]+1;
dfs(aa[i].en,x);
R[x]=max(R[x],R[aa[i].en]);
}
}
inline void update(int k){
int l=tr[k].l,r=tr[k].r,i;
for(i=0;i<=1;++i){
tr[k].mi[i]=tr[k].ma[i]=tr[k][i];
if(l){
tr[k].mi[i]=min(tr[k].mi[i],tr[l].mi[i]);
tr[k].ma[i]=max(tr[k].ma[i],tr[l].ma[i]);
}
if(r){
tr[k].mi[i]=min(tr[k].mi[i],tr[r].mi[i]);
tr[k].ma[i]=max(tr[k].ma[i],tr[r].ma[i]);
}
}
}
#define mid (l+r)/2
inline int build(int l,int r,int flag){
if(l>r) return 0;
D=flag;nth_element(p+l,p+mid,p+r+1);
tr[mid]=p[mid];
tr[mid].l=build(l,mid-1,flag^1);
tr[mid].r=build(mid+1,r,flag^1);
update(mid);
return mid;
}
inline bool in(int k,int x1,int y1,int x2,int y2){
return tr[k].mi[0]>=x1&&tr[k].ma[0]<=y1&&tr[k].mi[1]>=x2&&tr[k].ma[1]<=y2;
}
inline bool out(int k,int x1,int y1,int x2,int y2){
return tr[k].mi[0]>y1||tr[k].ma[0]<x1||tr[k].mi[1]>y2||tr[k].ma[1]<x2;
}
inline bool in1(int k,int x1,int y1,int x2,int y2){
return tr[k][0]>=x1&&tr[k][0]<=y1&&tr[k][1]>=x2&&tr[k][1]<=y2;
}
inline void pushdown(int k){
int l=tr[k].l,r=tr[k].r,c=tr[k].de;
if(l) tr[l].de=tr[l].c=c;
if(r) tr[r].de=tr[r].c=c;
tr[k].de=0;
}
inline void insert(int k,int x1,int y1,int x2,int y2,int c){
if(x1>y1||x2>y2||!k) return ;
if(in(k,x1,y1,x2,y2)){
tr[k].de=tr[k].c=c;
return ;
}
if(out(k,x1,y1,x2,y2)) return ;
if(tr[k].de) pushdown(k);
if(in1(k,x1,y1,x2,y2)) tr[k].c=c;
int l=tr[k].l,r=tr[k].r;
if(l&&tr[l].de!=c) insert(tr[k].l,x1,y1,x2,y2,c);
if(r&&tr[r].de!=c) insert(tr[k].r,x1,y1,x2,y2,c);
}
inline int query(int k,int flag){
if(now==tr[k]) return tr[k].c;
if(tr[k].de) pushdown(k);
if(now[flag]==tr[k][flag]){
if(now[flag^1]<tr[k][flag^1]) return query(tr[k].l,flag^1);
else return query(tr[k].r,flag^1);
}
else if(now[flag]<tr[k][flag]) return query(tr[k].l,flag^1);
else return query(tr[k].r,flag^1);
}
int main(){
T=in();
while(T--){
tot=dfsn=0;
memset(point,0,sizeof(point));
int i,x,j,y,z,ans=0;
n=in();m=in();m=in();
for(i=2;i<=n;++i){
x=in();
add(x,i);
}
dfs(1,0);
for(i=1;i<=n;++i){
p[i].c=1;
p[i].de=0;
p[i][0]=pos[i];
p[i][1]=deep[i];
for(j=0;j<=1;++j)
p[i].mi[j]=p[i].ma[j]=p[i][j];
}
root=build(1,n,0);
for(i=1;i<=m;++i){
x=in();y=in();z=in();
if(z) insert(root,L[x],R[x],deep[x],deep[x]+y,z);
else{
now[0]=pos[x];
now[1]=deep[x];
int c=query(root,0);
ans=(ans+(int)(((LL)c*(LL)i)%Mod))%Mod;
}
}
printf("%d\n",ans);
}
}