二维KD-Tree是一种将平面用一种玄学的方式分割成多份的数据结构
其操作功能强大
1:找最近||最远点,利用矩形区域计算最大最小可能值来剪枝,随机数据期望复杂度O(logn) ,构造数据。。。。。。不过可以用来优化求min/max之类的DP,DP式中数据应该近乎随机。
2.覆盖关键点的二维线段树问题:
如 BZOJ4154——IPSC2015 Generating Synergy
当问题可以转化为二维平面上的问题,并且可以存下关键点,还是可以用KD-Tree的
ACcode:
#include<cstdio>
#include<cstring>
#include<cctype>
#include<vector>
#include<algorithm>
#define mod 1000000007
#define maxn 100005
using namespace std;
int n,c,q;
vector<int>g[maxn];
int dfn[maxn],tot,st[maxn],ed[maxn],dep[maxn];
void dfs(int now)
{
++tot;
st[dfn[tot]=now]=tot;
for(int i=0,siz=g[now].size();i<siz;i++)
{
dep[g[now][i]]=dep[now]+1;
dfs(g[now][i]);
}
ed[now]=tot;
}
int D,root;
struct Point
{
int d[2];
bool operator <(const Point &Ano)const{ return d[D]<Ano.d[D]; }
}P[maxn];
struct Area
{
int d[2],x[2],y[2],son[2];
int col,tag;
}tr[maxn];
void upd(int now,int pre)
{
tr[now].x[0]=min(tr[now].x[0],tr[pre].x[0]);
tr[now].x[1]=max(tr[now].x[1],tr[pre].x[1]);
tr[now].y[0]=min(tr[now].y[0],tr[pre].y[0]);
tr[now].y[1]=max(tr[now].y[1],tr[pre].y[1]);
}
void dcd(int now)
{
if(tr[now].tag)
{
tr[tr[now].son[0]].tag=tr[tr[now].son[1]].tag=tr[tr[now].son[0]].col=tr[tr[now].son[1]].col=tr[now].tag;
tr[now].tag=0;
}
}
int build(int L,int R,int dir)
{
D=dir;int mid=(L+R)>>1;
nth_element(P+L,P+mid,P+R+1);
tr[mid].col=1,tr[mid].tag=0;
tr[mid].d[0]=tr[mid].x[0]=tr[mid].x[1]=P[mid].d[0];
tr[mid].d[1]=tr[mid].y[0]=tr[mid].y[1]=P[mid].d[1];
if(L<mid) tr[mid].son[0]=build(L,mid-1,dir^1),upd(mid,tr[mid].son[0]);
else tr[mid].son[0]=0;
if(mid<R) tr[mid].son[1]=build(mid+1,R,dir^1),upd(mid,tr[mid].son[1]);
else tr[mid].son[1]=0;
return mid;
}
void insert(int now,int x0,int x1,int y0,int y1,int Col)
{
dcd(now);
if(x1<tr[now].x[0] || x0>tr[now].x[1] || y1<tr[now].y[0] || y0>tr[now].y[1]) return;
if(x0<=tr[now].x[0] && tr[now].x[1]<=x1 && y0<=tr[now].y[0] && tr[now].y[1]<=y1)
{ tr[now].tag=tr[now].col=Col;return; }
if(x0<=tr[now].d[0] && tr[now].d[0]<=x1 && y0<=tr[now].d[1] && tr[now].d[1]<=y1) tr[now].col=Col;
insert(tr[now].son[0],x0,x1,y0,y1,Col);
insert(tr[now].son[1],x0,x1,y0,y1,Col);
}
int Query(int now,int x,int y)
{
dcd(now);
if(x<tr[now].x[0] || x>tr[now].x[1] || y<tr[now].y[0] || y>tr[now].y[1]) return 0;
if(x==tr[now].d[0] && y==tr[now].d[1]) return tr[now].col;
return Query(tr[now].son[0],x,y)+Query(tr[now].son[1],x,y);
}
int main()
{
int T;scanf("%d",&T);
for(;T--;)
{
int ans=0;
scanf("%d%d%d",&n,&c,&q);
for(int i=1;i<=n;i++) g[i].clear();
for(int i=2,u;i<=n;i++)
{
scanf("%d",&u);
g[u].push_back(i);
}
tot=0;
dep[1]=1;
dfs(1);
for(int i=1;i<=n;i++) P[i].d[0]=st[i],P[i].d[1]=dep[i];
root=build(1,n,0);
for(int i=1,a,l,c;i<=q;i++)
{
scanf("%d%d%d",&a,&l,&c);
if(!c)
ans=(ans+1ll*Query(root,st[a],dep[a])*i%mod)%mod;
else
insert(root,st[a],ed[a],dep[a],dep[a]+l,c);
}
printf("%d\n",ans);
}
}