【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. 蓝桥杯试题----- 打印大X

    打印大X 小明希望用星号拼凑,打印出一个大X,他要求能够控制笔画的宽度和整个字的高度.为了便于比对空格,所有的空白位置都以句点符来代替. 要求输入两个整数m n,表示笔的宽度,X的高度.用空格分开(0 ...

  2. 【Java每日一题】20170209

    20170208问题解析请点击今日问题下方的“[Java每日一题]20170209”查看(问题解析在公众号首发,公众号ID:weknow619) package Feb2017; public cla ...

  3. MyBatis学习笔记(二) Executor

    一.概述 当我们打开一个SqlSession的时候,我们就完成了操作数据库的第一步,那MyBatis是如何执行Sql的呢?其实MyBatis的增删改查都是通过Executor执行的,Executor和 ...

  4. python多线程-共享全局变量

    目录 多线程-共享全局变量 多线程-共享全局变量 列表当作实参传递到线程中 总结 多线程-共享全局变量问题 多线程开发可能遇到的问题 测试1 测试2 多线程-共享全局变量 多线程-共享全局变量 imp ...

  5. SpringBoot 之基础学习篇.

    一.概念简介 SpringBoot 的关键词是“约定俗成”,它根据长久以来的 Spring 开发配置经验,整理出一套适用.普遍.大家都认可的配置方案.所以 SpringBoot 的学习过程中心态一定要 ...

  6. Flask 系列之 HelloWorld

    说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环境管理器:virtualenv 代码编辑器:VS Code 实验目标 创建一个显示 Hello World 页面的网站. 环境 ...

  7. laravel中请求用例$request可用的一些方法小结

    laravel中$request可用的一些方法小结 1,请求方法的获取 $method = $request->method(); 2,检测请求方法 $res = $request->is ...

  8. C# Dev XtraReport 简单测试

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using DevExpre ...

  9. K8S 部署 ingress-nginx (二) 部署后端为 tomcat

    在上面已经部署了 ingress-nginx, https://www.cnblogs.com/klvchen/p/9903480.html 创建 service 和 pods cd vi tomca ...

  10. OSI 七层,TCP 四层 , TCP 五层模型介绍

    以 TCP 四层模型为例,介绍对应的物理设备 传输层: 四层交换机,四层路由器 网络层: 路由器,三层交换机 数据链路层: 网桥,以太网交换机,网卡 物理层: 中继器,集线器,双绞线 各层功能介绍 物 ...