【BZOJ 4449】[Neerc2015]Distance on Triangulation 多边形分治结构
这题好神啊……
正解方向是分治,据我所知的分治方法有:I.离线后直接对多边形以及所有的询问进行分治 II.建立多边形的分治结构(对于三角形来说类似线段树,对于对角线来说类似平衡树),然后每次在这个分治结构上进行查询 III.将原图转为其对偶图(利用拓扑),发现是一棵树,然后在这棵树上进行分治(似乎也有离线分治和在线建立分治结构两种方法)
我用的是第二种方法,感觉写起来不是很容易,但是也并不恶心,具体实现以及具体问题的处理方法见代码.
感觉这样分治的复杂度是log的,实际证明最坏情况下存在使得任意一侧的三角形数不少于n/3的分发,然而并不会证,大该感性理解一下吧.
思维笔记:I.分治无处不在 II.分治就是分治,也可以没有信息的合并 III.分治的出发点也可以是砍半,就像二分一样 IV.分治结构的建立类似分治,而分治结构的使用更像是二分
算法笔记:I.建立分治结构时所需信息,以及分治结构所需维护的信息,是不一样的,分开考虑与处理会方便得多 II.在分治结构中,储存信息的方式可以是对于每个点存储其在每一层的信息,也可以是对于每一层存储每个点的信息,两者各有千秋,在这道题里,个人感觉前者用起来更加方便 III.这道题分治的理由我感觉是——一个对角线把多边形切成两个部分,如果询问的两个点都在这两个部分里的其中一个里面,那这次询问一定与另一部分无关
#pragma GCC optimize("O3")
#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#define pb push_back
#define ft first
#define sd second
#define mmp(a,b) (std::make_pair(a,b))
char xB[(<<)+],*xS,*xT;
#define gtc (xS==xT&&(xT=((xS=xB)+fread(xB,1,1<<15,stdin)),xS==xT)?0:*xS++)
inline void read(int &x){
register char ch=gtc;
for(x=;ch<''||ch>'';ch=gtc);
for(;ch>=''&&ch<='';x=(x<<)+(x<<)+ch-'',ch=gtc);
}
typedef std::pair<int,int> pii;
typedef std::vector<int> vi;
typedef std::vector<pii> vii;
const int A=,N=,Inf=0x3f3f3f3f;
vi tmp1;
vii tmp2;
struct Block{
Block *ch[];
pii cut;
}*root,block[N<<];
#define newblock (block+(sz++))
int to[N][A],dis[N][A][];
int q[N],front,back,vis[N],id[N];
int n;
struct V{int to,next;}c[N<<];
int head[N],t;
inline void add(int x,int y){
c[++t].to=y,c[t].next=head[x],head[x]=t;
c[++t].to=x,c[t].next=head[y],head[y]=t;
}
int sz,cnt;
inline void bfs(int S,int deep,int opt){
++cnt,front=back=,q[back++]=S;
dis[S][deep][opt]=,vis[S]=cnt;
register int x,i;
while(front!=back){
x=q[front++];
for(i=head[x];i;i=c[i].next)
if(vis[c[i].to]!=cnt){
vis[c[i].to]=cnt;
dis[c[i].to][deep][opt]=dis[x][deep][opt]+;
q[back++]=c[i].to;
}
}
}
inline void build(Block *&p,register vi poi,register vii cut,int deep){
p=newblock;
if(cut.size()==)return;
pii mini;
int min=Inf,temp,size1=poi.size(),size2=cut.size();
register int i;
for(i=;i<size2;++i){
temp=std::abs(id[cut[i].ft]-id[cut[i].sd])+;
temp=std::max(temp,size1-temp+);
if(temp<min)
min=temp,mini=cut[i];
}
p->cut=mini;
int l=id[mini.ft],r=id[mini.sd];
if(l>r)std::swap(l,r);
tmp1.clear(),tmp2.clear();
for(i=;i<=l;++i){
tmp1.pb(poi[i]);
id[poi[i]]=tmp1.size()-;
to[poi[i]][deep]=;
}
for(i=r;i<size1;++i){
tmp1.pb(poi[i]);
id[poi[i]]=tmp1.size()-;
to[poi[i]][deep]=;
}
for(i=;i<size2;++i){
if(cut[i]==mini)continue;
if(to[cut[i].ft][deep]==&&to[cut[i].sd][deep]==)
tmp2.pb(cut[i]);
}
build(p->ch[],tmp1,tmp2,deep+);
tmp1.clear(),tmp2.clear();
for(i=l;i<=r;++i){
tmp1.pb(poi[i]);
id[poi[i]]=i-l;
to[poi[i]][deep]=;
}
for(i=;i<size2;++i){
if(cut[i]==mini)continue;
if(to[cut[i].ft][deep]==&&to[cut[i].sd][deep]==)
tmp2.pb(cut[i]);
}
build(p->ch[],tmp1,tmp2,deep+);
for(i=;i<size1;++i)head[poi[i]]=;
t=;
for(i=;i<size1;++i)
add(poi[i],poi[i-]);
add(poi[size1-],poi[]);
for(i=;i<size2;++i)
add(cut[i].ft,cut[i].sd);
bfs(mini.ft,deep,);
bfs(mini.sd,deep,);
}
inline int query(Block *p,int x,int y,int deep){
if(!p->ch[])return ;
if(p->cut.ft==x)return dis[y][deep][];
if(p->cut.sd==x)return dis[y][deep][];
if(p->cut.ft==y)return dis[x][deep][];
if(p->cut.sd==y)return dis[x][deep][];
if(to[x][deep]==to[y][deep])return query(p->ch[to[x][deep]],x,y,deep+);
int ret=dis[x][deep][]+dis[y][deep][];
ret=std::min(ret,dis[x][deep][]+dis[y][deep][]);
return ret;
}
int main(){
read(n);
register int i;pii rio;
for(i=;i<=n;++i)
tmp1.pb(i),id[i]=i-;
for(i=;i<=n-;++i)
read(rio.ft),read(rio.sd),tmp2.pb(rio);
build(root,tmp1,tmp2,);
int T,x,y;
read(T);
while(T--){
read(x),read(y);
printf("%d\n",x==y?:query(root,x,y,));
}
return ;
}
【BZOJ 4449】[Neerc2015]Distance on Triangulation 多边形分治结构的更多相关文章
- bzoj 4449: [Neerc2015]Distance on Triangulation
Description 给定一个凸n边形,以及它的三角剖分.再给定q个询问,每个询问是一对凸多边行上的顶点(a,b),问点a最少经过多少条边(可以是多边形上的边,也可以是剖分上的边)可以到达点b. I ...
- 【bzoj 4449】[Neerc2015]Distance on Triangulation
Description 给定一个凸n边形,以及它的三角剖分.再给定q个询问,每个询问是一对凸多边行上的顶点(a,b),问点a最少经过多少条边(可以是多边形上的边,也可以是剖分上的边)可以到达点b. I ...
- BZOJ4449 : [Neerc2015]Distance on Triangulation
首先拓扑,每次取出度数为$2$的点,这样可以把所有三角形都找到. 那么建出对偶图,会发现是一棵树. 对这棵树进行点分治,每次取出重心,DFS求出所有在里面的点,然后从重心$3$个点分别做一次BFS. ...
- BZOJ 4012 HNOI2015 开店 树的边分治+分治树
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4012 题意概述:给出一颗N点的树,保证树上所有点的度不超过3,树上每个点有权值,每条边有权 ...
- POJ 1987 BZOJ 3365 Distance Statistics 树的分治(点分治)
题目大意:(同poj1741,刷一赠一系列) CODE: #include <cstdio> #include <cstring> #include <iostream& ...
- BZOJ.4738.[清华集训2016]汽水(点分治 分数规划)
BZOJ UOJ 记\(val_i\)是每条边的边权,\(s\)是边权和,\(t\)是经过边数,\(k\)是给定的\(k\). 在点分治的时候二分答案\(x\),设\(|\frac st-k|=x\) ...
- NOI 2007 货币兑换Cash (bzoj 1492) - 斜率优化 - 动态规划 - CDQ分治
Description 小Y最近在一家金券交易所工作.该金券交易所只发行交易两种金券:A纪念券(以下简称A券)和 B纪念券(以下 简称B券).每个持有金券的顾客都有一个自己的帐户.金券的数目可以是一个 ...
- CodeChef - PRIMEDST Prime Distance On Tree 树分治 + FFT
Prime Distance On Tree Problem description. You are given a tree. If we select 2 distinct nodes unif ...
- bzoj 3784: 树上的路径【点分治+st表+堆】
参考:https://www.cnblogs.com/CQzhangyu/p/7071477.html 神奇的点分治序(或者叫点剖?).就是把点分治扫过的点依次放进队列里,然后发现,对于每一棵树摊到序 ...
随机推荐
- Python基础入门(迭代器和生成器)
1 Python迭代器 迭代器是一个可以记住遍历的位置的对象. 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束. 迭代器只能往前不会后退. 迭代器有两个基本的方法:iter() 和 ...
- JavaScript学习笔记(五)——类型、转换、相等、字符串
第六章 类型 相等 转换等 一.类型 1 typeof(); typeof是一个内置的JavaScript运算符,可用于探测其操作数的类型. 例: <script language=" ...
- 该用哪个:Redis与Memcached之间如何选择呢?
华为云分布式缓存Redis5.0和Memcached都是华为云DCS的核心产品. 那么在不同的使用场景之下,如何选择Redis5.0和Memcached呢? 就由小编为大家进行详细的数据对比分析吧 R ...
- leetcode12_C++整数转罗马数字
小弟不才,有错误或者更好解,求留言. 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, ...
- 支持向量机SVM 初识
虽然已经学习了神经网络和深度学习并在几个项目之中加以运用了,但在斯坦福公开课上听吴恩达老师说他(在当时)更喜欢使用SVM,而很少使用神经网络来解决问题,因此来学习一下SVM的种种. 先解释一些概念吧: ...
- Wacom将在CES 2015上发布全新旗舰版Cintiq
Cintiq 27QHD和Cintiq 27QHD touch拥有宽大的工作表面,以及令人惊喜的屏幕笔触和颜色性能. 2015年1月6日,Wacom发布了Cintiq 27QHD和Cintiq 27Q ...
- 初试Gevent – 高性能的Python并发框架
Gevent是一个基于greenlet的Python的并发框架,以微线程greenlet为核心,使用了epoll事件监听机制以及诸多其他优化而变得高效. 于greenlet.eventlet相比,性能 ...
- python knn自我实践
#得到分类数据和测试数据 import pymysql import struct from numpy import * a=['']*20 #存图像 分类数据 b=[[0]*76800]*20#存 ...
- CS小分队第二阶段冲刺站立会议(5月30日)
昨日成果:解决了前天遗留的问题,实现了主界面对于电脑上应用的添加和删除 遇到问题:添加和删除按钮时候,按钮位置图像与北京图片冲突,会出现闪动现象. 删除是通过右键单击出现菜单,其中有删除的选项,但是这 ...
- 2018软工实践—Alpha冲刺(6)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 测试服务器并行能力 学习MSI.CUDA ...