题面:https://www.lydsy.com/JudgeOnline/problem.php?id=4154
KD树代替数据结构的主要思路:把限制条件转化到KD树上面的维度来进行计算
题解
用KD树的思路比较简单
先把整棵树的dfs序:dfn数组求出来,随便把每个点的深度dep和子树大小siz求出来
把点的坐标视为(dfn[i],dep[i])
修改操作及对dfn[x]<=dfn[i]<=dfn[x]+siz[x]-1 , dep[x]<=dep[i]<=dep[x]+y 的所有i进行区间覆盖颜色z
单点查询就直接把当前点到根的路径上的懒标记下放
然后不到25min就水过去了。。。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
inline int gi()
{
char c;int num=0,flg=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flg=-1;
while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}
return num*flg;
}
#define N 100005
#define lc ch[i][0]
#define rc ch[i][1]
const int mod=1000000007;
const int INF=0x3f3f3f3f;
int fir[N],to[N],nxt[N],cnt;
int siz[N],dep[N],dfn[N],dc;
void adde(int a,int b){to[++cnt]=b;nxt[cnt]=fir[a];fir[a]=cnt;}
void dfs(int u,int ff)
{
dep[u]=dep[ff]+1;dfn[u]=++dc;siz[u]=1;
for(int p=fir[u];p;p=nxt[p]){dfs(to[p],u);siz[u]+=siz[to[p]];}
}
int D;
int ch[N][2],fa[N],rt,tot;
int tmp[N];
int a[N][2],mi[N][2],mx[N][2];
int la[N],col[N];
int qmi[2],qmx[2];
inline void pushup(int i)
{
mi[i][0]=min(min(mi[lc][0],mi[rc][0]),a[i][0]);
mx[i][0]=max(max(mx[lc][0],mx[rc][0]),a[i][0]);
mi[i][1]=min(min(mi[lc][1],mi[rc][1]),a[i][1]);
mx[i][1]=max(max(mx[lc][1],mx[rc][1]),a[i][1]);
}
inline void pushdown(int i)
{
if(la[i]){
if(lc)la[lc]=col[lc]=la[i];
if(rc)la[rc]=col[rc]=la[i];
la[i]=0;
}
}
inline bool cmp(const int &x,const int &y){return a[x][D]<a[y][D];}
void build(int &i,int l,int r,int d)
{
int mid=(l+r)>>1;D=d;
nth_element(tmp+l,tmp+mid,tmp+r+1,cmp);
i=tmp[mid];lc=rc=0;
if(l<mid)build(lc,l,mid-1,d^1);
if(r>mid)build(rc,mid+1,r,d^1);
pushup(i);fa[lc]=fa[rc]=i;
}
void insert(int &i,int k)
{
if(!i)return;
pushdown(i);
if(mi[i][0]>qmx[0]||qmi[0]>mx[i][0]||mi[i][1]>qmx[1]||qmi[1]>mx[i][1])return;
if(qmi[0]<=mi[i][0]&&mx[i][0]<=qmx[0]&&qmi[1]<=mi[i][1]&&mx[i][1]<=qmx[1]){col[i]=la[i]=k;return;}
if(qmi[0]<=a[i][0]&&a[i][0]<=qmx[0]&&qmi[1]<=a[i][1]&&a[i][1]<=qmx[1])col[i]=k;
if(lc)insert(lc,k);
if(rc)insert(rc,k);
}
void pdpath(int i)
{
if(fa[i])pdpath(fa[i]);
pushdown(i);
}
int main()
{
int T,n,m,Q,i,x,y,z,ans;
T=gi();
while(T--){
ans=0;
memset(fir,0,sizeof(fir));cnt=0;dc=0;
memset(dep,0,sizeof(dep));
memset(dfn,0,sizeof(dfn));
memset(siz,0,sizeof(siz));
memset(fa,0,sizeof(fa));
memset(ch,0,sizeof(ch));rt=tot=0;
memset(tmp,0,sizeof(tmp));
memset(a,0,sizeof(a));
memset(mi,0,sizeof(mi));
memset(mx,0,sizeof(mx));
memset(la,0,sizeof(la));
mi[0][0]=mi[0][1]=INF;
mx[0][0]=mx[0][1]=-INF;
n=gi();m=gi();Q=gi();
for(i=2;i<=n;i++){
x=gi();
adde(x,i);
}
dfs(1,0);
for(i=1;i<=n;i++){
a[i][0]=dfn[i];
a[i][1]=dep[i];
tmp[++tot]=i;col[i]=1;
}
build(rt,1,tot,0);
for(i=1;i<=Q;i++){
x=gi();y=gi();z=gi();
if(!z){
pdpath(x);
ans=(1ll*ans+1ll*col[x]*i)%mod;
}
else{
qmi[0]=dfn[x];qmx[0]=dfn[x]+siz[x]-1;
qmi[1]=dep[x];qmx[1]=dep[x]+y;
insert(rt,z);
}
}
printf("%d\n",ans);
}
}