BZOJ 4154 [Ipsc2015]Generating Synergy
2018.03.07
2018.03.07
给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色。
DFS序一维,深度一维,建立二维KD-Tree,之后跑一下就好了.
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1000000
#define MO 1000000007
#define R register
#define ls p[pos].c[0]
#define rs p[pos].c[1]
int to[N+1],nex[N+1],head[N+1],tot;
long long ans;
int cnt,id[N+1],depth[N+1],siz[N+1],rt,ref[N+1];
int md;
struct node
{
int c[2],v[2],mx[2],mn[2],cl,lz,fa,ref;
bool operator<(const node &tg)const
{
if(v[md]==tg.v[md]) return v[md^1]<tg.v[md^1];
return v[md]<tg.v[md];
}
}p[N+1];
char nc()
{
static char buf[100000],*p1,*p2;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
int RI()
{
R int ret=0;R char tmp=nc();
while(!isdigit(tmp)) tmp=nc();
while(isdigit(tmp)) ret=ret*10+(tmp^'0'),tmp=nc();
return ret;
}
inline void AE(int tx,int ty){to[++tot]=ty,nex[tot]=head[tx],head[tx]=tot;}
void DFS(int pos)
{
siz[pos]=1;
id[pos]=++cnt;
for(int i=head[pos];i;i=nex[i])
{
depth[to[i]]=depth[pos]+1;
DFS(to[i]);
siz[pos]+=siz[to[i]];
}
}
inline void pushup(int pos)
{
p[pos].mx[0]=max(p[pos].v[0],max(p[ls].mx[0],p[rs].mx[0]));
p[pos].mx[1]=max(p[pos].v[1],max(p[ls].mx[1],p[rs].mx[1]));
p[pos].mn[0]=min(p[pos].v[0],min(p[ls].mn[0],p[rs].mn[0]));
p[pos].mn[1]=min(p[pos].v[1],min(p[ls].mn[1],p[rs].mn[1]));
}
inline void pushdown(int pos)
{
if(p[pos].lz) p[ls].cl=p[rs].cl=p[ls].lz=p[rs].lz=p[pos].lz,p[pos].lz=0;
}
int build(int l,int r,int now)
{
if(l>r) return 0;
int mid=(l+r)>>1;
md=now;
nth_element(p+l,p+mid,p+r+1);
p[mid].c[0]=build(l,mid-1,now^1),p[p[mid].c[0]].fa=mid;
p[mid].c[1]=build(mid+1,r,now^1),p[p[mid].c[1]].fa=mid;
pushup(mid);
return mid;
}
void color(int pos,int w,int a,int s,int d,int tg)
{
if(!pos||p[pos].mx[0]<a||p[pos].mn[0]>d||p[pos].mn[1]>w||p[pos].mx[1]<s) return;
if(p[pos].mn[0]>=a&&p[pos].mx[0]<=d&&p[pos].mx[1]<=w&&p[pos].mn[1]>=s)
{
p[pos].cl=p[pos].lz=tg;
return;
}
pushdown(pos);
if(p[pos].v[0]>=a&&p[pos].v[0]<=d&&p[pos].v[1]>=s&&p[pos].v[1]<=w) p[pos].cl=tg;
color(p[pos].c[0],w,a,s,d,tg);
color(p[pos].c[1],w,a,s,d,tg);
}
int query(int pos)
{
if(p[pos].fa) query(p[pos].fa);
pushdown(pos);
return p[pos].cl;
}
int main()
{
R int T;
T=RI();
while(T--)
{
cnt=ans=tot=0;memset(head,0,sizeof head),memset(siz,0,sizeof siz);
R int n=RI(),c=RI(),q=RI(),ix,iy,iz;
for(int i=0;i<=n;++i)
p[i].mx[0]=p[i].mx[1]=-0x3f3f3f3f,p[i].mn[0]=p[i].mn[1]=0x3f3f3f3f,p[i].cl=1,p[i].fa=p[i].lz=0;
for(int i=2;i<=n;++i) AE(RI(),i);
DFS(1);
for(int i=1;i<=n;++i) p[i].v[0]=id[i],p[i].v[1]=depth[i],p[i].ref=i;
rt=build(1,n,0);
for(int i=1;i<=n;++i) ref[p[i].ref]=i;
for(int i=1;i<=q;++i)
{
ix=RI(),iy=RI(),iz=RI();
if(!iz) ans=(ans+1ll*i*query(ref[ix]))%MO;
else color(rt,depth[ix]+iy,id[ix],depth[ix],id[ix]+siz[ix]-1,iz);
}
printf("%lld\n",ans);
}
return 0;
}