【NOI2018模拟5】三角剖分Bsh

Description

  给定一个正 n 边形及其三角剖分,共 2n - 3 条边 (n条多边形的边和n-3 条对角线),每条边的长度为 1。

  共 q 次询问,每次询问给定两个点,求它们的最短距离。

Input

  第一行一个整数 n ,表示多边形的点数;

  接下来 n - 3 行,每行两个整数 ui,vi,表示一条 ai 和 bi 之间的对角线;

  接下来一行一个整数 q,表示询问个数;

  接下来 q 行,每行两个整数 xi,yi,表示第 i 次询问的起点和终点;

Output

  对于每一个询问输出一个整数,表示答案。

Sample Input

6

1 5

2 4

5 2

5

1 3

2 5

3 4

6 3

6 6

Sample Output

2

1

1

3

0

\(n\leq 52000,1\leq q\leq 2n\)

因为这是个平面图,我们发现,选取一条边之后可以将图分为两个部分,两个部分之间的最短路一定经过了这条边的两个端点中至少一个。

又因为这是三角剖分,所以我们可以找到中间点使得左右两边的点数非常接近。所以我们可以分治。

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 150000 using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;} int n,m;
struct road {
int to,nxt;
}s[N<<1];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;} #define pr pair<int,int>
#define mp(a,b) make_pair(a,b) bool vis[N];
int dis1[N],dis2[N];
queue<int>q;
void bfs(int S,int *dis) {
q.push(S);
dis[S]=0;
while(!q.empty()) {
int v=q.front();
q.pop();
for(int i=h[v];i;i=s[i].nxt) {
int to=s[i].to;
if(!vis[to]) continue ;
if(dis[to]>1e9) {
dis[to]=dis[v]+1;
q.push(to);
}
}
}
} struct query {int x,y,id;}; int pre[N];
int ans[N];
int tag1[N],tag2[N]; int tim;
void solve(vector<int>V,vector<pr>E,vector<query>Q) {
if(!Q.size()) return ;
if(V.size()==3) {
for(int i=0;i<Q.size();i++) {
int x=Q[i].x,y=Q[i].y;
if(x==y) ans[Q[i].id]=0;
else ans[Q[i].id]=1;
}
return ;
}
int n=V.size(),m=E.size();
int mid=(n-2)>>1;
for(int i=0;i<n;i++) pre[V[i]]=0;
pre[V[0]]=1;
for(int i=1;i<n;i++) pre[V[i]]=pre[V[i-1]]+1;
int id;
int X=0,Y=0;
int MN=1e9;
for(int i=0;i<m;i++) {
int x=E[i].first,y=E[i].second;
int now=pre[y]-pre[x]-1;
if(max(now,n-2-now)<MN) {
MN=max(now,n-2-now);
X=x,Y=y;
}
}
vector<int>v1,v2;
vector<pr>e1,e2;
vector<query>q1,q2;
v1.clear(),e1.clear(),q1.clear();
v2.clear(),e2.clear(),q2.clear();
for(int i=0;i<n;i++) {
if(X<=V[i]&&V[i]<=Y) tag1[V[i]]=1;
if(V[i]>=Y||V[i]<=X) tag2[V[i]]=1;
}
for(int i=0;i<n;i++) {
if(tag1[V[i]]) v1.push_back(V[i]);
if(tag2[V[i]]) v2.push_back(V[i]);
}
for(int i=0;i<m;i++) {
int x=E[i].first,y=E[i].second;
if(tag1[x]&&tag1[y]) e1.push_back(E[i]);
if(tag2[x]&&tag2[y]) e2.push_back(E[i]);
}
for(int i=0;i<Q.size();i++) {
if(tag1[Q[i].x]&&tag1[Q[i].y]) q1.push_back(Q[i]);
if(tag2[Q[i].x]&&tag2[Q[i].y]) q2.push_back(Q[i]);
}
for(int i=0;i<n;i++) {
dis1[V[i]]=dis2[V[i]]=1e9+7;
vis[V[i]]=1;
}
bfs(X,dis1);
bfs(Y,dis2);
for(int i=0;i<Q.size();i++) {
int x=Q[i].x,y=Q[i].y,id=Q[i].id;
ans[id]=min(ans[id],dis1[x]+dis1[y]);
ans[id]=min(ans[id],dis2[x]+dis2[y]);
ans[id]=min(ans[id],dis1[x]+dis2[y]+1);
ans[id]=min(ans[id],dis2[x]+dis1[y]+1);
}
for(int i=0;i<n;i++) tag1[V[i]]=tag2[V[i]]=vis[V[i]]=0;
solve(v1,e1,q1),solve(v2,e2,q2);
} vector<int>V;
vector<pr>E;
vector<query>Q;
int main() {
n=Get();
for(int i=1;i<n;i++) add(i,i+1),add(i+1,i);
add(1,n),add(n,1);
for(int i=1;i<=n-3;i++) {
int x=Get(),y=Get();
add(x,y),add(y,x);
if(x>y) swap(x,y);
E.push_back(mp(x,y));
}
memset(ans,0x3f,sizeof(ans));
for(int i=1;i<=n;i++) V.push_back(i);
m=Get();
for(int i=1;i<=m;i++) {
int x=Get(),y=Get();
if(x>y) swap(x,y);
Q.push_back((query) {x,y,i});
}
solve(V,E,Q);
for(int i=1;i<=m;i++) cout<<ans[i]<<"\n";
return 0;
}

【NOI2018模拟5】三角剖分Bsh的更多相关文章

  1. BSOJ5458 [NOI2018模拟5]三角剖分Bsh 分治最短路

    题意简述 给定一个正\(n\)边形及其三角剖分,每条边的长度为\(1\),给你\(q\)组询问,每次询问给定两个点\(x_i\)至\(y_i\)的最短距离. 做法 显然正多边形的三角剖分是一个平面图, ...

  2. JZOJ 5602.【NOI2018模拟3.26】Cti

    JZOJ 5602.[NOI2018模拟3.26]Cti Description 有一个 \(n×m\) 的地图,地图上的每一个位置可以是空地,炮塔或是敌人.你需要操纵炮塔消灭敌人. 对于每个炮塔都有 ...

  3. 【NOI2018模拟】Yja

    [NOI2018模拟]Yja Description 在平面上找\(n\)个点,要求这 \(n\)个点离原点的距离分别为 \(r1,r2,...,rn\) .最大化这\(n\) 个点构成的凸包面积,凸 ...

  4. 【JZOJ5605】【NOI2018模拟3.26】Arg

    题目描述 给出一个长度为 m 的序列 A, 请你求出有多少种 1...n 的排列, 满足 A 是它的一个 LIS. 解题思路 如何求出一个序列的LIS? 对于二分的方法,每次插入一个数,将它放到第一个 ...

  5. 【JZOJ5603】【NOI2018模拟3.27】Xjz

    题目描述 给定字符串 S 和 T. 串A和串B匹配的定义改为:存在一个字符的映射,使得A应用这个映射之后等于B,且这个映射必须为一个排列. A=121, B=313,当映射为{1->3, 2-& ...

  6. NOIP2018 模拟赛(二十二)雅礼NOI

    Preface 这次的题目都是NOI+的题,所以大家的分数都有点惨烈. 依靠T1大力骗分水到Rank2 所以想看正解的话看这里吧 A. 「雅礼NOI2018模拟赛(一) Day1」树 看一眼题目感觉十 ...

  7. 【XSY2968】线性代数

    题目来源:noi2018模拟测试赛(二十二) 毒瘤板题+提答场……真tm爽 提答求最大团,各路神仙退火神仙随机化八仙过海 题意: 题解: 支持双端插入的回文自动机板题 代码: #include< ...

  8. 【XSY2892】【GDSOI2018】谁是冠军

    题目来源:noi2018模拟测试赛(二十三)T3 san 为什么noi模拟赛里会做到省选原题啊…… 题意: Description 有n个人,简单起见把他们编号为1到n,每个人有三项指标分别是攻击力, ...

  9. 【XSY2989】字符串

    题目来源:NOI2018模拟测试赛(二十六) 题解: 首先由于这是个01串,所以反对称串的意思就是这个字符串的后半部分是前半部分的反转且翻转结果: 一个串出现有三种情况:在前半部分,在后半部分或穿过中 ...

随机推荐

  1. c# json 序列化时遇到错误 error Self referencing loop detected for type

    参考网址:http://blog.csdn.net/adenfeng/article/details/41622255 在写redis缓存帮助类的时候遇到的这个问题,本来打算先序列化一个实体为json ...

  2. vb.net 多线程運用 ping

    Imports System.IOImports System.ThreadingImports System.Diagnostics Public Class Form1 Dim A(254) As ...

  3. [PHP] 算法-顺时针打印矩阵的PHP实现

    1.行数和列数取出来row,col,圈数就是 (较小值-1)/2+1 2.外层循环控制圈数,内层四个for循环,i 3.第一个for循环,从左到右,j=i;j<col-i;j++;j<; ...

  4. 程序猿制造Bug的根本原因竟然是....

    传说中: 「杀一个程序猿不需要用枪,改三次需求就可以了.」 而且, 「这竟然也是程序猿制造Bug的根本原因....」 ↓↓↓↓↓↓↓ #/原始需求/#   你去饭店,坐下来. “服务员,给我来份宫保鸡 ...

  5. Java实现Base64加密

    阅读本文约“2.5分钟” Java加解密系列,介绍Java加密解密的基础知识,并使用Base64算法实现加解密. 对于加密在企业中是非常常见的,就如邮件的传输,每个企业都会有自己设置安全方式,设置加密 ...

  6. Cheating sheet for vim

  7. vue-cli 3.x 开发插件并发布到 npm

    为了摆脱咸鱼的身份,我给自己定了一个开源项目的目标 于是抽空写了一个 textarea,打算发布到 npm 的时候却遇到了问题 之前用 vue-cli 2.x 的时候,打包配置项非常透明,可以很容易的 ...

  8. Angular的12个经典问题,看看你能答对几个?(文末附带Angular测试)

    Angular作为目前最为流行的前端框架,受到了前端开发者的普遍欢迎.不论是初学Angular的新手,还是有一定Angular开发经验的开发者,了解本文中的12个经典面试问题,都将会是一个深入了解和学 ...

  9. 五. Redis持久化

    Redis是一个支持可持久化的内存数据库,也就是说Redis可以将数据保存到硬盘当中. 目前Redis支持两种持久化方式: 1. snapshotting 快照方式(默认方式). 2. append- ...

  10. 自定义View类

    一.如何创建自定义的View类 ①.创建一个继承android.view.View类的Java类,并且重写构造方法(至少需要重写一个构造方法) ②.根据需要重写其他方法 ③.在项目的活动中,创建并实例 ...