传送门

题解:
这是经典的KD树模型,所以直接KD树优化建边即可。

不过需要注意的是KD树上的点不能是原来的点,要新建一个映射点连向原来的点,因为原来的点如果增加了本来没有的连边会对答案有影响。。

(刚才搜了搜好像全是线段树?? 赶紧去学一学)

upt::
线段树做法,可持久化线段树合并,比kd树好打多了。。
Code : https://paste.ubuntu.com/26511273/

#include <bits/stdc++.h>
using namespace std;
inline int rd() {char ch=getchar(); int i=0,f=1;while(!isdigit(ch)) {if(ch=='-')f=-1; ch=getchar();}while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=getchar();}return i*f;
}
const int N=2e5+50;
int n,tot,dfn[N],dep[N],sze[N],id[N],ind;
int scc,xc[N],d[N],low[N],st[N],ins[N],tp;
long long ans;
struct point {int x,y;point(){}point(int x,int y):x(x),y(y){}
}que[N];
inline bool cmpx(const point &a,const point &b) {return a.x<b.x;}
inline bool cmpy(const point &a,const point &b) {return a.y<b.y;}
struct node {node *lc,*rc;point p;int o;int mx[2],mn[2];inline void upt(node *x,node *y) {y->mx[0]=max(y->mx[0],x->mx[0]);y->mx[1]=max(y->mx[1],x->mx[1]);y->mn[0]=min(y->mn[0],x->mn[0]);y->mn[1]=min(y->mn[1],x->mn[1]);}inline void upt() {mx[0]=(mn[0]=p.x);mx[1]=(mn[1]=p.y);if(lc)upt(lc,this);if(rc)upt(rc,this);}
}nd[N],*rt=nd+1,*pool=rt;
struct Graph*G;
struct Graph{vector <int> edge[N];inline void init(int sze) {for(int i=1;i<=sze;i++) edge[i].clear();}inline void add(int x,int y) {if(x==y) return;edge[x].push_back(y);}inline void dfs(int x) {dfn[x]=++ind; id[ind]=x; sze[x]=1;for(int e=edge[x].size()-1;e>=0;e--) {int v=edge[x][e]; dep[v]=dep[x]+1;dfs(v); sze[x]+=sze[v];}que[x]=point(dfn[x],dep[x]);}inline void build(node *&now,int l,int r,int dim) {now=++pool;now->o=++tot;if(l==r) {now->p=que[l];G->add(tot,id[now->p.x]);now->upt();return;} int mid=(l+r)>>1;if(dim) nth_element(que+l,que+mid,que+r+1,cmpy);else nth_element(que+l,que+mid,que+r+1,cmpx);now->p=que[mid];G->add(tot,id[now->p.x]);if(l<mid) build(now->lc,l,mid-1,dim^1),G->add(now->o,now->lc->o);if(r>mid) build(now->rc,mid+1,r,dim^1),G->add(now->o,now->rc->o);now->upt();}inline int cmp(const point &mn,const point &mx,node *now) {if(now->mx[0]<mn.x||now->mx[1]<mn.y) return -1;if(now->mn[0]>mx.x||now->mn[1]>mx.y) return -1;if(now->mn[0]>=mn.x&&now->mn[1]>=mn.y&&now->mx[0]<=mx.x&&now->mx[1]<=mx.y) return 1;return 0;}inline bool in(const point &mn,const point &mx,const point &p) {return p.x>=mn.x&&p.x<=mx.x&&p.y>=mn.y&&p.y<=mx.y;}inline void findarea(node *now,int i,const point &mn,const point &mx) {if(!now) return;int t=cmp(mn,mx,now);if(t==-1) return;if(t==1) G->add(i,now->o);else {findarea(now->lc,i,mn,mx);findarea(now->rc,i,mn,mx);if(in(mn,mx,now->p)) G->add(i,id[now->p.x]);}}inline void build() {ind=0; dfs(1);G->init(2*n);pool=rt;for(int i=1;i<=n;i++) nd[i].lc=NULL,nd[i].rc=NULL;build(rt,1,n,0);for(int i=1;i<=n;i++) {findarea(rt,i,point(dfn[xc[i]],dep[xc[i]]),point(dfn[xc[i]]+sze[xc[i]]-1,dep[xc[i]]+d[i]));}}inline void tarjan(int x) {dfn[x]=(low[x]=++ind); ins[x]=1; st[++tp]=x;for(int e=edge[x].size()-1;e>=0;e--) {int v=edge[x][e];if(!dfn[v]) tarjan(v),low[x]=min(low[x],low[v]);else if(ins[v]) low[x]=min(low[x],dfn[v]);}if(low[x]==dfn[x]) {++scc; sze[scc]=0;int u;do{u=st[tp--];ins[u]=0;if(u<=n) ++sze[scc];}while(u!=x);ans+=((long long)sze[scc]*(sze[scc]-1)/2);}}inline void tarjan() {ind=0; scc=0;memset(dfn+1,0,sizeof(int)*tot);for(int i=1;i<=tot;i++) if(!dfn[i])tarjan(i);}
}tr,gh;
inline void solve() {n=rd(); tot=n;tr.init(n);for(int i=2;i<=n;i++) tr.add(rd(),i);for(int i=1;i<=n;i++) xc[i]=rd(),d[i]=rd();tr.build();ans=0;gh.tarjan();printf("%lld\n",ans);
}
int main() {G=&gh;int T=rd();while(T--) solve();
}

HDU5420:Victor and Proposition(KD树)相关推荐

  1. HDU5420 : Victor and Proposition

    以深度建立线段树,线段树父亲节点向儿子节点连边,然后用线段树合并可以得到任何一个点子树的线段树,只需向对应节点的线段树中的$O(\log n)$个点连边即可.为了保证连边关系不发生混乱,线段树需要进行 ...

  2. hdu 5420 Victor and Proposition 线段树建图+强连通分量

    题意: http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=620&pid=1003 题目求有多少对互为充要 ...

  3. kd树 python实现_Python KD树实现+简单的KNN实现

    写KD树的时候没把类别考虑进去...所以先用KD算出最近的k个点,然后找到对应分类最后输出占比最大的 KD树是一种二叉树,用来分割空间上得点 一个树节点的结构如下: class TreeNode: i ...

  4. K-近邻算法之kd树

    K-近邻算法之kd树 问题导入: 实现k近邻法时,主要考虑的问题是如何对训练数据进行快速k近邻搜索. 这在特征空间的维数大及训练数据容量大时尤其必要. k近邻法最简单的实现是线性扫描(穷举搜索),即要 ...

  5. KNN分类器、最近邻分类、KD树、KNN分类的最佳K值、基于半径的最近邻分类器、KNN多分类、KNN多标签分类、KNN多输出分类、KNN分类的优缺点

    KNN分类器.最近邻分类.KD树.KNN分类的最佳K值.基于半径的最近邻分类器.KNN多分类.KNN多标签分类.KNN多输出分类.KNN分类的优缺点 目录

  6. KD树是什么? 为什么要用KD树? KD树怎么用? KD树和KNN的关联是什么?

    KD树是什么? 为什么要用KD树? KD树怎么用? KD树和KNN的关联是什么? sklearn中如何配置? 为了提高KNN的搜索效率,这里介绍一种可以减少计算距离次数的方法---KD树方法. KD树 ...

  7. KD树和LSH局部敏感哈希

    文档结构 文档表示 距离度量 KD树 原理 构建 查询 复杂度 KD树的KNN KD树的逼近KNN 不适用高维数据 LSH LSH潜在的问题 LSH算法 复杂度 概率逼近 多表 文档结构 文档表示 词 ...

  8. 统计学习方法笔记(二)-kd树原理及python实现

    kd树 kd树简介 构造平衡kd树算法原理 kd树代码实现 案例地址 kd树简介 kdkdkd树是一种对kkk维空间中的实例点进行存储以便对其进行快速检索的树形数据结构. kdkdkd树构造方法: 构 ...

  9. KD树——k=1时就是BST,里面的数学原理还是有不明白的地方,为啥方差划分?...

    Kd-Tree,即K-dimensional tree,是一棵二叉树,树中存储的是一些K维数据.在一个K维数据集合上构建一棵Kd-Tree代表了对该K维数据集合构成的K维空间的一个划分,即树中的每个结 ...

最新文章

  1. 【Binder 机制】AIDL 分析 ( 创建 Service 服务 | 绑定 Service 远程服务 )
  2. Headmaster's Headache
  3. UE4 + UnLua + VSCode + LuaPanda调试
  4. python所有软件都打不开机怎么办_电脑软件,小编教你电脑所有软件都打不开怎么解决...
  5. Angular 下拉搜索框实现
  6. putc函数_C语言中的putc()函数与示例
  7. 计算机科学申请文书,美国留学:看牛人怎么写申请计算机CS专业的文书
  8. 各种字符串合并处理示例.sql
  9. ETL学习总结(2)——ETL数据集成工具之kettle、sqoop、datax、streamSets 比较
  10. Kotlin入门(3)基本变量类型的用法
  11. 用于创建二维数组的语法
  12. YOLO系列专题——Complex-YOLO
  13. 虚拟机自省XenAccess和vmitools
  14. 美丽中国 纪录片 高频词 GRE 托福词汇
  15. 身份证号码正则表达式及校验方法
  16. library netcdf 路径_科学网—NetCDF安装记录 - 丁鹏基的博文
  17. Linux 系统日常运维九大技能和运维网络知识总结
  18. 计算机图形学(第四版)-第一个画线例子- 读书笔记P30
  19. 使用注解开发(重点)
  20. 赛尔号服务器维护时间4月27,赛尔号03月27日更新攻略汇总 瀚海界神重获新生

热门文章

  1. 基于RKE部署的rancher管理平台迁移
  2. 毕业3年,我辞职考研(2)
  3. 断臂求生 东芝转型欲做“隐形巨头”
  4. Python|Pymol的安装
  5. Flink 部署模式,session 、pre job、aplication三种主要模式
  6. Android调起高德地图
  7. python 等高线地图 处理_python中不规则网格上地图覆盖等高线
  8. 纯前端导出 wordexcel表格
  9. 服务器配置怎么选择硬件配置
  10. Oracle 删除分区 导致索引失效