【NOI2018模拟5】三角剖分Bsh
【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的更多相关文章
- BSOJ5458 [NOI2018模拟5]三角剖分Bsh 分治最短路
题意简述 给定一个正\(n\)边形及其三角剖分,每条边的长度为\(1\),给你\(q\)组询问,每次询问给定两个点\(x_i\)至\(y_i\)的最短距离. 做法 显然正多边形的三角剖分是一个平面图, ...
- JZOJ 5602.【NOI2018模拟3.26】Cti
JZOJ 5602.[NOI2018模拟3.26]Cti Description 有一个 \(n×m\) 的地图,地图上的每一个位置可以是空地,炮塔或是敌人.你需要操纵炮塔消灭敌人. 对于每个炮塔都有 ...
- 【NOI2018模拟】Yja
[NOI2018模拟]Yja Description 在平面上找\(n\)个点,要求这 \(n\)个点离原点的距离分别为 \(r1,r2,...,rn\) .最大化这\(n\) 个点构成的凸包面积,凸 ...
- 【JZOJ5605】【NOI2018模拟3.26】Arg
题目描述 给出一个长度为 m 的序列 A, 请你求出有多少种 1...n 的排列, 满足 A 是它的一个 LIS. 解题思路 如何求出一个序列的LIS? 对于二分的方法,每次插入一个数,将它放到第一个 ...
- 【JZOJ5603】【NOI2018模拟3.27】Xjz
题目描述 给定字符串 S 和 T. 串A和串B匹配的定义改为:存在一个字符的映射,使得A应用这个映射之后等于B,且这个映射必须为一个排列. A=121, B=313,当映射为{1->3, 2-& ...
- NOIP2018 模拟赛(二十二)雅礼NOI
Preface 这次的题目都是NOI+的题,所以大家的分数都有点惨烈. 依靠T1大力骗分水到Rank2 所以想看正解的话看这里吧 A. 「雅礼NOI2018模拟赛(一) Day1」树 看一眼题目感觉十 ...
- 【XSY2968】线性代数
题目来源:noi2018模拟测试赛(二十二) 毒瘤板题+提答场……真tm爽 提答求最大团,各路神仙退火神仙随机化八仙过海 题意: 题解: 支持双端插入的回文自动机板题 代码: #include< ...
- 【XSY2892】【GDSOI2018】谁是冠军
题目来源:noi2018模拟测试赛(二十三)T3 san 为什么noi模拟赛里会做到省选原题啊…… 题意: Description 有n个人,简单起见把他们编号为1到n,每个人有三项指标分别是攻击力, ...
- 【XSY2989】字符串
题目来源:NOI2018模拟测试赛(二十六) 题解: 首先由于这是个01串,所以反对称串的意思就是这个字符串的后半部分是前半部分的反转且翻转结果: 一个串出现有三种情况:在前半部分,在后半部分或穿过中 ...
随机推荐
- .NET页面导出Excel
public static void CreateExcel(DataSet ds) { string filename = DateTime.Now.ToStri ...
- Java基础篇——JVM之GC原理(干货满满)
原创不易,如需转载,请注明出处https://www.cnblogs.com/baixianlong/p/10697554.html ,多多支持哈! 一.什么是GC? GC是垃圾收集的意思,内存处理是 ...
- 学习 Docker 操作系统版本选择
近来有时间一直在捣鼓 Docker.因为服务器选择的是 CentOS 版本,所以实验的环境选择的一直是 CentOS.如果是个人玩 Docker,优先选择 ubuntu.如果需要选择 CentOS 的 ...
- 微信小程序-查询快递
1.新建快速启动项目 2.在设置里面勾选不校验合法域名,以防编译报错 3.在app.json中改一下窗口表现:app.json—"navigationBarTitleText": ...
- POJ1275 Cashier Employment(差分约束)
Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 9078 Accepted: 3515 Description A sup ...
- 【机器学习基本理论】详解最大似然估计(MLE)、最大后验概率估计(MAP),以及贝叶斯公式的理解
[机器学习基本理论]详解最大似然估计(MLE).最大后验概率估计(MAP),以及贝叶斯公式的理解 https://mp.csdn.net/postedit/81664644 最大似然估计(Maximu ...
- 教你分分钟搞定Docker私有仓库Registry
一.什么是Docker私有仓库Registry 官方的Docker hub是一个用于管理公共镜像的好地方,我们可以在上面找到我们想要的镜像,也可以把我们自己的镜像推送上去.但是,有时候我们的服务器无法 ...
- 2 >&1 的准确含义
1. 2代表标准错误,2 > 表示重定向,就是把标准错误重定向到 1中,这个1如果想表示标准输出的话,就必须在前面加 & 2. 正常情况下,下面这个会有很多错误信息,但是加上2>& ...
- Android开发CheckBox控件,全选,反选,取消全选
在Android开发中我们经常会使用CheckBox控件,那么怎么实现CheckBox控件的全选,反选呢 首先布局我们的界面: <?xml version="1.0" enc ...
- oracle11在docker环境下的运行
目的 Ø 在测试的环境下oracle数据库不存在或访问不方便时,可以将这个环境快速恢复出来 Ø 开发时方便测试之用 可以在任何包含docker服务的机器上运行,具体的docker的安装可以参考如下: ...