bzoj 4449: [Neerc2015]Distance on Triangulation
Description
给定一个凸n边形,以及它的三角剖分。再给定q个询问,每个询问是一对凸多边行上的顶点(a,b),问点a最少经过多少条边(可以是多边形上的边,也可以是剖分上的边)可以到达点b。
Input
第一行一个整数n(n <= 50000),代表有n个点。点1,2,3,…,n是凸多边形上是顺时针排布的。
Output
#include<bits/stdc++.h>
char buf[],*ptr=buf+;
int G(){
if(ptr-buf==)fread(ptr=buf,,,stdin);
return *ptr++;
}
int _(){
int x=;
if(ptr-buf<){
while(*ptr<)++ptr;
while(*ptr>)x=x*+*ptr++-;
}else{
int c=G();
while(c<)c=G();
while(c>)x=x*+c-,c=G();
}
return x;
}
const int N=,inf=0x3f3f3f3f,P=;
int n,qp,idp=;
int deg[N],q[N],ql=,qr=,as[N];
std::vector<int>e0[N],ee[N];
struct Q{int w,id;};
std::vector<Q>qq[N];
Q*qs[N][];
int sz[N],*lr[N][],*et[N][];
int p3[N][];
void ae(int a,int b){
++deg[b];++deg[a];
e0[a].push_back(b);
e0[b].push_back(a);
} struct hash_map{
int h[P][];
int*operator()(int a,int b){
if(a>b)std::swap(a,b);
int w=(a*+b*)%P;
while(h[w][]){
if(h[w][]==a&&h[w][]==b)return h[w]+;
if((w+=)>=P)w-=P;
}
h[w][]=a,h[w][]=b;
return h[w]+;
}
}h1,h2;
void chk(int a,int b){
if(a>b)std::swap(a,b);
if(a==&&b==n||a+==b)return;
int*w=h1(a,b);
if(w[]){
int x=idp,y=w[];
ee[x].push_back(y);
ee[y].push_back(x);
int*c=h2(x,y);
c[]=a;c[]=b;
}else w[]=idp;
}
int ss[N][],sp,tk=,ed[N],ed2[N];
int ps[N],pp=;
void ins(int a){
for(int t=;t<;++t){
int w=p3[a][t];
if(ed2[w]!=tk)ed2[ps[pp++]=w]=tk;
}
}
void f2(int w,int pa){
sz[w]=;
ed[w]=tk;
ss[sp][]=w,ss[sp++][]=pa;
for(int*l=lr[w][],*r=lr[w][];l!=r;++l){
int u=*l;
if(u==pa)continue;
f2(u,w);
sz[w]+=sz[u];
}
}
void dele(int a,int b){
for(int*l=lr[a][],*r=lr[a][];l!=r;++l)if(*l==b){
*l=*--lr[a][];
return;
}
}
int min(int a,int b){return a<b?a:b;}
void mins(int&a,int b){if(a>b)a=b;}
int d1[N],d2[N],dd1[N],dd2[N],dk=;
bool qd[N];
void bfs(int w,int*d,int*dd){
ql=qr=;
dd[q[++qr]=w]=dk,d[w]=;
while(ql!=qr){
w=q[++ql];
for(int*l=et[w][],*r=et[w][];l!=r;++l){
int u=*l;
if(ed2[u]==tk&&dd[u]!=dk)dd[q[++qr]=u]=dk,d[u]=d[w]+;
}
}
}
void f1(int w){
++tk;
pp=;
sp=;
f2(w,);
int SZ=sz[w];
if(SZ>){
int mx=,p1=w,p2=;
for(int i=;i<sp;++i){
int u=ss[i][],mv=min(sz[u],SZ-sz[u]);
if(mv>mx)mx=mv,p1=u,p2=ss[i][];
ins(u);
}
dele(p1,p2);
dele(p2,p1);
int*ns=h2(p1,p2);
++dk;
bfs(ns[],d1,dd1);bfs(ns[],d2,dd2);
for(int i=;i<pp;++i){
int u=ps[i];
int d1u=d1[u];
int d2u=d2[u];
for(Q*l=qs[u][],*r=qs[u][];l!=r;++l){
int v=l->w;
if(qd[v])*l--=*(qs[u][]=--r);
else if(ed2[v]==tk){
int d1v=d1[v];
int d2v=d2[v];
mins(as[l->id],min(min(d1u+d1v,d2u+d2v),min(d1u+d2v+,d2u+d1v+)));
}
}
}
qd[ns[]]=qd[ns[]]=;
for(int d=;d<;++d)qs[ns[d]][]=qs[ns[d]][];
f1(p1);f1(p2);
}
}
int main(){
n=_();
for(int i=,a,b;i<=n-;++i){
a=_();b=_();
ae(a,b);
}
for(int i=;i<=n;++i)ae(i,i==n?:i+);
for(int i=;i<=n;++i){
et[i][]=e0[i].data();
et[i][]=et[i][]+e0[i].size();
}
for(int i=;i<=n;++i)if(deg[i]==)q[++qr]=i;
while(ql!=qr){
int w=q[++ql];
if(deg[w]!=)break;
deg[w]=;
int cs[],cp=;
cs[cp++]=w;
for(int*l=et[w][],*r=et[w][];l!=r;++l){
int u=*l;
if(!deg[u])continue;
cs[cp++]=u;
if(==--deg[u])q[++qr]=u;
}
++idp;
for(int i=;i<;++i){
for(int j=;j<i;++j)chk(cs[i],cs[j]);
p3[idp][i]=cs[i];
}
}
for(int i=;i<=idp;++i){
lr[i][]=ee[i].data();
lr[i][]=lr[i][]+ee[i].size();
}
qp=_();
for(int i=;i<qp;++i){
int x=_(),y=_();
if(x==y)continue;
if(x>y)std::swap(x,y);
if(x==&&y==n||x+==y||h1(x,y)[]){
as[i]=;
continue;
}
as[i]=inf;
qq[x].push_back((Q){y,i});
qq[y].push_back((Q){x,i});
}
for(int i=;i<=idp;++i){
qs[i][]=qq[i].data();
qs[i][]=qs[i][]+qq[i].size();
}
f1();
for(int i=;i<qp;++i)printf("%d\n",as[i]);
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 多边形分治结构
这题好神啊……正解方向是分治,据我所知的分治方法有:I.离线后直接对多边形以及所有的询问进行分治 II.建立多边形的分治结构(对于三角形来说类似线段树,对于对角线来说类似平衡树),然后每次在这个分治结 ...
- BZOJ4449 : [Neerc2015]Distance on Triangulation
首先拓扑,每次取出度数为$2$的点,这样可以把所有三角形都找到. 那么建出对偶图,会发现是一棵树. 对这棵树进行点分治,每次取出重心,DFS求出所有在里面的点,然后从重心$3$个点分别做一次BFS. ...
- Gym 100851 Distance on Triangulation
题意:给你一个N边形, 然后这个n边形有n-3条边,然后询问2点之间的最短路. 题解:分治. 我们可以找到一条边,使得这幅图能分成大小相同的2幅图,那么我们就可以确定那些被分割开的询问的答案是多少了. ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- NOIP模拟赛 城市
题目描述 $ZZQ$ 是一国之主. 这个国家有$N$个城市, 第$i$个城市与第$(i + 1) (mod N)$和$(i - 1) (mod N)$在一个正$N$边形相连. $ZZQ$ 又新建了$N ...
- Week Two
2018.12.3: 1.[BZOJ 4819] 2.[BZOJ 4827] 3.[P1919] 4.[FFT模板] 2018.12.4: 1.[NTT] 2.[MTT(CRT)] 3.[MTT(my ...
- NEERC15
2015-2016 ACM-ICPC Northeastern European Regional Contest 再开一个新坑吧 目前姿势有限,C.H.I仍然处于弃坑状态 代码戳这里 Problem ...
- 【刷题】BZOJ 3365 [Usaco2004 Feb]Distance Statistics 路程统计
Description 在得知了自己农场的完整地图后(地图形式如前三题所述),约翰又有了新的问题.他提供 一个整数K(1≤K≤109),希望你输出有多少对农场之间的距离是不超过K的. Input 第1 ...
随机推荐
- L1-002 打印沙漏
所谓“沙漏形状”,是指每行输出奇数个符号:各行符号中心对齐:相邻两行符号数差2:符号数先从大到小顺序递减到1,再从小到大顺序递增:首尾符号数相等. 给定任意N个符号,不一定能正好组成一个沙漏.要求打印 ...
- wavepicking
http://www.seismology.harvard.edu/research/wavePicking.html
- Bad update sites
Bad update sites com.genuitec.pulse2.client.common.launcher.BadUpdateSiteException Software being in ...
- Jmeter系列培训(1)--开山篇
一直以来,我们不断分享,有的人喜欢,也有的人不喜欢,这都没什么,喜欢的点个赞,留个言,不喜欢的就不看好了,今天我们继续,关于jmeter我们分享了很多工作遇到的问题的解决方案,但是很多 ...
- Centos中查看系统信息的常用命令
系统日志文件(可以通过cat或tail命令来查看) /var/log/message 系统启动后的信息和错误日志,是Red Hat Linux中最常用的日志之一 /var/log/secure 与安全 ...
- matlab mod()&rem()
一.介绍rem/mod(X,Y)当X,Y符号相同的时候,这两者一样,当符号不相同的时候才有差别,具体表现在rem结果的符号与被除数相同:mod结果的符号与除数相同 二.例子 >> a=9; ...
- socket can demo
http://www.cnblogs.com/zengjfgit/p/5327689.html
- 任务02——安装 Intellj IDEA,编写一个简易四则运算小程序,并将代码提交到 GitHub
github地址:https://github.com/ErhuoHome/First.git 安装jdk与intellij idea没有太大问题,以前安装过eclipse 在程序方面,由于对真分数的 ...
- HBulider打包
1. manifest配置 按照Manifest.json文档说明 manifest配置把工程中的manifest.json文件配置好,下面以我的项目为例进行配置. (1).应用信息 (2).图标配置 ...
- 51Nod:1085 背包问题
1085 背包问题 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 在N件物品取出若干件放在容量为W的背包里,每件物品的体积为W1,W2--Wn(Wi为 ...