【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. Tomcat 8005/8009/8080/8443端口的作用

    --关闭tomcat进程所用.当执行shutdown.sh关闭tomcat时就是连接8005端口执行“SHUTDOWN”命令--由此,我们直接telnet8005端口执行“SHUTDOWN”(要大写, ...

  2. Linux学习笔记之基本指令

    1.ll 注:详细展示当前文件夹下的所有文件及目录  ,与 ls -al 有异曲同工的作用 2.free -m/-h 注:-m:显示当前的内存信息,-m表示以MB为单位显示:-h:以人类能读懂的形式显 ...

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

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

  4. 改变Tomcat在地址栏上显示的小猫图标

    部署在Tomcat上的项目通常在地址栏会显示一个小猫的图标,那么如何改变这个图标呢? 第一步.制作自己显示的图标 这里使用的是在线制作的方式,推荐一个在线制作的网站---比特虫:http://www. ...

  5. Java8 默认方法

    概述 Java8新增了接口的默认方法.使用default关键字. 默认方法就是接口可以有实现方法,而且不需要实现类来实现其方法.相对于JDK1.8之前的接口来说,新增了可以接口中实现方法. 可以说在接 ...

  6. angular ztree 梯形结构json配置、点击节点事件、默认展开所有

    // 获取树数据 $scope.initZtreeData = function () { var url = '/bpopstation/func/queryAll.do'; $http.post( ...

  7. canvas-6shadow.html

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. js内置对象-Object

    1)Object构造函数的方法 返回指定对象的原型对象 Object.getPrototypeOf(mymap); /*{featureStyle: {…}, selfLayersCount: nul ...

  9. Android为TV端助力 转载:Java 泛型

    一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: 1 public class GenericTest { 2 3 public static void main(Stri ...

  10. Native SBS for Android

    Native SBS for Android是一款非常棒的软件,支持安卓在2D界面下左右分屏显示,并可以设置缩放比例及左右间距,横屏自动切换为左右分屏显示模式,竖屏则为正常显示.启动左右分屏模式后,将 ...