【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 神奇的点分治序(或者叫点剖?).就是把点分治扫过的点依次放进队列里,然后发现,对于每一棵树摊到序 ...
随机推荐
- Phaser3让超级玛丽实现轻跳、高跳及加上对应的跳跃声音
mario jumper 在线测试地址:http://www.ifiero.com/uploads/phaserjs3/jumper/ 空格键:轻按:跳低 ,长按:跳高键盘:--> 向右 , ...
- 53. [LeetCode] Maximum Subarray
Given an integer array nums, find the contiguous subarray (containing at least one number) which has ...
- 剑指 Offer——数字在排序数组中出现的次数
1. 题目 2. 解答 时间复杂度为 \(O(n)\) 的算法,顺序遍历数组,当该数字第一次出现时开始记录次数. class Solution { public: int GetNumberOfK(v ...
- Adobe InDesign CS6自学入门到高级视频教程
关键字:Adobe InDesign 视频教程 点击获取视频教程 教程目录 第1章/1.卸载InDesign CS6.avi 第1章/2.安装InDesign CS6.avi 第2章/1.创建并编辑自 ...
- 分布式数据库中间件Mycat百亿级数据存储(转)
此文转自: https://www.jianshu.com/p/9f1347ef75dd 2013年阿里的Cobar在社区使用过程中发现存在一些比较严重的问题,如高并发下的假死,心跳连接的故障,只实现 ...
- “Hello World!“”团队第五周召开的第二次会议
今天是我们团队“Hello World!”团队第五周召开的第二次会议.也祝大家双十一快乐~~博客内容: 一.会议时间 二.会议地点 三.会议成员 四.会议内容 五.todo list 六.会议照片 七 ...
- 【探路者】互评beta版本
成员博客 1蔺依铭:http://www.cnblogs.com/linym762/ 2张恩聚:http://www.cnblogs.com/zej87/ 3米赫:http://www.cnblogs ...
- 【java】中缀表达式转后缀表达式 java实现
算法: 中缀表达式转后缀表达式的方法:1.遇到操作数:直接输出(添加到后缀表达式中)2.栈为空时,遇到运算符,直接入栈3.遇到左括号:将其入栈4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出 ...
- ARP 攻击
场景 A攻击者 192.168.1.3 00:00:00:00:00:01 B受害者 192.168.1.2 00:00:00:00:00:02 C路由器 192.168.1.1 00:00:00:0 ...
- 【BioCode】根据seq与位点信息截取窗口
代码说明 sequence24371.txt 以上为所有氨基酸的编号,序列,与位点标记.根据标记为“1”的位点,截取窗口:如下(实验结果): 图示为一个窗口为12的蛋白质片段 2N+1=25: 实现代 ...