一种按点划分,对于随机数据表现良好的非常规二维数据结构(二维KD树)

130 篇文章 1 订阅
92 篇文章 0 订阅

二维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);
	}
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值