[WC2013]平面图

码农题

平面图点定位:

1.平面图转对偶图:[HNOI2016]矿区

2.扫描线点定位

把所有的顶点和询问点排序,扫描线

每个边在fr的位置加入,to的位置删除,竖直直线不要

用set维护当前的线段,kx+b形式

全局变量X放入重载小于号的比较函数,便于直接比较

到了询问点,直接查询上方第一个线段,得到这个线段所属对偶图新点的编号,即可得到这个询问点的位置

(需要在线就可持久化平衡树吧。。)

trick:

A.可以把询问点当做:0*x+p[i].y,直接查询即可

B.避免插入删除时候纵坐标一样的麻烦,X+=0.1后插入,X-=0.1后删除

C.询问上方第一个线段,(我的对偶图内部是顺时针),所以保留to的横坐标比fr的大的边即可,省去了线段重合的麻烦

然后求MST之后倍增找到链上最大值即可

实现

扫描线时候:

直接开vector把涉及的插入线段,删除线段,询问点直接塞进去,直接查询即可

可能有重边!

这个时候必须保留最小值,先把所有边sort之后再加入。

但是注意:b[++m]=bian(...,...,...m)bian构造函数传进去的m还是之前的m!并没有++m

所以把++m放外面先做

另外,总涉及点数是3*n的。

大致解释

code:并不能过UOJhack数据

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
#define pb push_back
#define solid const auto &
#define enter cout<<endl
#define pii pair<int,int>
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
char ch;x=;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
for(x=numb;isdigit(ch=getchar());x=x*+numb);(fl==true)&&(x=-x);}
template<class T>il void output(T x){if(x/)output(x/);putchar(x%+'');}
template<class T>il void ot(T x){if(x<) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');} namespace Miracle{
const int N=1e5+;
const int inf=0x3f3f3f3f;
int n,m,q;
struct lj{
int x,y,z;
bool friend operator <(lj a,lj b){
return a.z<b.z;
}
}name[N];
map<pii,int>exi;
//pre---------------------------------------------------------------------------//
struct po{
double x,y;
po(){}
po friend operator -(po a,po b){return po(a.x-b.x,a.y-b.y);}
po(double xx,double yy){
x=xx;y=yy;
}
bool friend operator <(po a,po b){
return a.x<b.x;
}
double friend operator *(po a,po b){
return a.x*b.y-a.y*b.x;
}
}p[*N];
int num;
double degree(const po &A){
return atan2(A.y,A.x);
}
struct line{
int fr,to;
int cos;
int id;
double deg;
line(){}
line(int a,int b,int c,int d){fr=a;to=b;cos=c;id=d;deg=degree(p[to]-p[fr]);}
bool friend operator <(line A,line B){
return A.deg<B.deg;
}
}b[*N];
vector<line>to[N];
int nxt[*N];
int nc;//newcur
int be[*N];
int findnxt(const line &A,const int &id){
int lp=upper_bound(to[id].begin(),to[id].end(),A)-to[id].begin();
if(lp==to[id].size()) lp=;
return to[id][lp].id;
}
struct edge{
int x,y,val;
bool friend operator <(edge a,edge b){
return a.val<b.val;
}
}mao[N];
int tot;//count
void trans(){
for(reg i=;i<=n;++i) sort(to[i].begin(),to[i].end());
for(reg i=;i<=m;++i){
nxt[i]=findnxt(b[i^],b[i].to);
}
for(reg i=;i<=m;++i){
if(be[i]) continue;
be[i]=be[nxt[i]]=++nc;
double S=;
for(reg j=nxt[i];j!=i;j=nxt[j]){
be[j]=nc;
S+=(p[b[j].to]-p[b[i].fr])*(p[b[j].fr]-p[b[i].fr]);
}
if(S<){
--nc;
be[i]=be[nxt[i]]=inf;
for(reg j=nxt[i];j!=i;j=nxt[j]){
be[j]=inf;
}
}
}
for(reg i=;i<=m;i+=){
if(be[i]!=inf&&be[i^]!=inf){
++tot;
mao[tot].x=be[i];
mao[tot].y=be[i^];
mao[tot].val=b[i].cos;
}
}
}
//trans-------------------------------------------------------------------------//
int gf[N];
int fin(int x){
return gf[x]==x?x:gf[x]=fin(gf[x]);
}
struct node{
int nxt,to;
int val;
}e[*N];
int hd[N],cnt;
void add(int x,int y,int z){
e[++cnt].nxt=hd[x];
e[cnt].to=y;
e[cnt].val=z;
hd[x]=cnt;
}
void kruskal(){
for(reg i=;i<=nc;++i) gf[i]=i;
sort(mao+,mao+tot+);
for(reg i=;i<=tot;++i){
int x=mao[i].x,y=mao[i].y;
int k1=fin(x),k2=fin(y);
if(k1!=k2){
gf[k1]=k2;
add(x,y,mao[i].val);
add(y,x,mao[i].val);
}
}
}
//kruskal-------------------------------------------------------------------------//
int dep[N],fa[N][],mx[N][];
void dfs(int x,int d){
dep[x]=d;
for(reg i=hd[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==fa[x][]) continue;
fa[y][]=x;
mx[y][]=e[i].val;
dfs(y,d+);
}
}
int query(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
int ret=;
for(reg j=;j>=;--j){
if(dep[fa[x][j]]>=dep[y]){
ret=max(ret,mx[x][j]);x=fa[x][j];
}
}
if(x==y) return ret;
for(reg j=;j>=;--j){
if(fa[x][j]!=fa[y][j]){
ret=max(ret,max(mx[x][j],mx[y][j]));
x=fa[x][j],y=fa[y][j];
}
}
ret=max(ret,max(mx[x][],mx[y][]));
return ret;
}
//dfs&&lca------------------------------------------------------------------------//
double X;
struct bian{
double k,b;
int id;
bian(){}
bian(double kk,double bb,double dd){
k=kk;b=bb;id=dd;
}
double f(){return k*X+b;}
bool friend operator <(bian A,bian B){
return A.f()<B.f();
}
void op() const {
cout<<" k "<<k<<" b "<<b<<" id "<<id<<endl;
}
};
multiset<bian>s;
int rk[*N];
bool cmp(int x,int y){
return p[x]<p[y];
}
vector<int>qs[*N];
vector<bian>del[*N];
vector<bian>ins[*N];
int qa[N],qb[N];
int in[*N];
int main(){
rd(n);int lp;rd(lp);
int x,y;
for(reg i=;i<=n;++i){
rd(x);rd(y);p[++num].x=x;p[num].y=y;
}
for(reg i=;i<=lp;++i){
rd(name[i].x);rd(name[i].y);rd(name[i].z);if(name[i].x>name[i].y) swap(name[i].x,name[i].y);
}sort(name+,name+lp+); m=-;//warning!! m=-1
for(reg i=;i<=lp;++i){
pii tmp=mk(name[i].x,name[i].y);
if(exi.count(tmp)) continue;
exi[tmp]=;++m;
b[m]=line(name[i].x,name[i].y,name[i].z,m);
to[name[i].x].push_back(b[m]);
++m;
b[m]=line(name[i].y,name[i].x,name[i].z,m);
to[name[i].y].push_back(b[m]);
}
trans();
kruskal();
dfs(,);
for(reg j=;j<=;++j){
for(reg i=;i<=nc;++i){
fa[i][j]=fa[fa[i][j-]][j-];
mx[i][j]=max(mx[i][j-],mx[fa[i][j-]][j-]);
}
}
rd(q);
for(reg i=;i<=q;++i){
po tmp;scanf("%lf",&tmp.x);scanf("%lf",&tmp.y);
++num;p[num]=tmp;
qa[i]=num;
scanf("%lf",&tmp.x);scanf("%lf",&tmp.y);
++num;p[num]=tmp;
qb[i]=num;
qs[qa[i]].push_back(qa[i]);
qs[qb[i]].push_back(qb[i]);
}
for(reg i=;i<=num;++i) rk[i]=i;
sort(rk+,rk+num+,cmp);
for(reg i=;i<=m;++i){
if(p[b[i].fr].x<p[b[i].to].x){
bian tmp;
tmp.k=(p[b[i].to].y-p[b[i].fr].y)/(p[b[i].to].x-p[b[i].fr].x);
tmp.b=p[b[i].fr].y-tmp.k*p[b[i].fr].x;
tmp.id=i;
ins[b[i].fr].push_back(tmp);
del[b[i].to].push_back(tmp);
}
}
for(reg i=;i<=num;++i){
int now=rk[i];
if(del[now].size()){
X=p[now].x-0.1;
for(solid y:del[now]){
auto it=s.find(y);
s.erase(it);
}
}
if(ins[now].size()){
X=p[now].x+0.1;
for(solid y:ins[now]){
s.insert(y);
}
}
if(qs[now].size()){
X=p[now].x;
for(solid y:qs[now]){
bian tmp=bian(,p[y].y,);
auto it=s.upper_bound(tmp);
if(it==s.end()){
in[y]=inf;
}else{
in[y]=be[(*it).id];
}
}
}
}
for(reg i=;i<=q;++i){
int x=in[qa[i]];
int y=in[qb[i]];
if(x==inf||y==inf){
puts("-1");
}else if(x==y){
puts("");
}else{
printf("%d\n",query(x,y));
}
}
return ;
} }
signed main(){
Miracle::main();
return ;
} /*
Author: *Miracle*
*/

[WC2013]平面图——平面图点定位的更多相关文章

  1. 平面图转对偶图(Bzoj1001:狼抓兔子)

    如果只会用最小割做这道题那就太菜辣 引入 来自某学长 平面图:在平面上边不相交的图(边可以绕着画) 那么平面图的边与边就围成了许多个区域(这与你画图的方式有关) 定义对偶图:把相邻的两个区域连上边,形 ...

  2. P3209-平面图判定

    平面图 平面图就是所有点的连边不相交的图.(当然是在你尽量想让它不相交的情况下).这一点可以大概理解成拓扑图的性质,即每连一条边就会将某个区域进行分割--很明显,如果两个点分别处在两个不可达的区域,它 ...

  3. 最大流最小割——bzoj1001狼抓兔子,洛谷P2598

    前置知识 平面图 平面图就是平面上任意边都不相交的图.(自己瞎画的不算XD) 对偶图 比如说这个图,我们发现平面图肯定会把平面分成不同的区域(感觉像拓扑图),并把这些区域当做每个点(不被包围的区域独自 ...

  4. 【uoj57】 WC2013—平面图

    http://uoj.ac/problem/57 (题目链接) 题意 给出二位平面上n个点,点之间有一些连线,连线不在顶点之外的地方相交,将平面分为若干个区域.给出一些询问点对,问从这个点所在的区域走 ...

  5. bzoj3051: [wc2013]平面图

    Description Input Output 扫描线求出平面图的对偶图然后求最小生成树,用并查集按秩合并,以便查询两点间路径最大权 #include<stdio.h> #include ...

  6. bzoj3051[WC2013]平面图(树上倍增+平面图转对偶图+扫描线)

    简要题意:二维平面上n个点,点之间有一些连线,连线不在点之外的地方相交,将平面分为若干个区域.给出一些询问点对,问从这个点所在的区域走到另一个点所在的区域的最小代价. 题解:这道题首先可以把平面图转对 ...

  7. 洛谷 P4073 [WC2013]平面图

    #include<bits/stdc++.h> using namespace std; ; typedef long double LD; ; ); int dcmp(LD x){ret ...

  8. 【BZOJ 3051】【UOJ #57】【WC 2013】平面图

    http://www.lydsy.com/JudgeOnline/problem.php?id=3051 http://uoj.ac/problem/57 这道题需要平面图转对偶图,点定位,最小生成树 ...

  9. 用Python制作中国地图、地球平面图及球形图

    绘制地图在python中主要用到的 basemap 库,这个库是 matplotlib 库中一个用于在 Python 中绘制地图上的 2D 数据的工具包. 首先安装库: 1.安装 geos 库:Pyt ...

随机推荐

  1. mysql实现行拼接、列拼接

    举例:有t_person表如下: 一.mysql行拼接: 拼接某一行: 无分隔符:select   CONCAT(id,idcard,`status`,content)   from  t_perso ...

  2. Leetcode892.Surface Area of 3D Shapes三维形体的表面积

    在 N * N 的网格上,我们放置一些 1 * 1 * 1  的立方体. 每个值 v = grid[i][j] 表示 v 个正方体叠放在单元格 (i, j) 上. 返回结果形体的总表面积. 示例 1: ...

  3. Leetcode703.Kth Largest Element in a Stream数据流中的第K大元素

    设计一个找到数据流中第K大元素的类(class).注意是排序后的第K大元素,不是第K个不同的元素. 你的 KthLargest 类需要一个同时接收整数 k 和整数数组nums 的构造器,它包含数据流中 ...

  4. 掀开SQL的神秘面纱,将优化进行到底

    掀开SQL的神秘面纱,将优化进行到底 有这样一条奇怪的SQL,返回结果不足10行,逻辑读达到1.2w,存在索引却走多次全表扫描,如何揭开它神秘的面纱拯救系统性能,答案在这里,你不可错过! 本文来自上周 ...

  5. PAT天梯赛L1-002 打印漏斗

    题目链接:点击打开链接 本题要求你写个程序把给定的符号打印成沙漏的形状.例如给定17个"*",要求按下列格式打印 ***** *** * *** ***** 所谓"沙漏形 ...

  6. 编程语言分类及python所属类型

    编程语言分类及python所属类型 编程语言主要从以下几个角度为进行分类:编译型和解释型.静态语言和动态语言.强类型定义语言和弱类型定义语言. 编译和解释的区别是什么? 编译器是把源程序的每一条语句都 ...

  7. oracle如何看审计的结果

    1)数据库初始化参数文件中AUDIT_TRAIL=OS时,审计记录存在操作系统的文件中. UNIX系统的话,默认存在“$oracle_home/rdbms/audit/” 目录下. If you ha ...

  8. Libevent:6辅助函数以及类型

    在头文件<event2/util.h>中定义了许多有用的函数和类型来帮助实现可移植的程序.Libevent在内部使用这些类型和函数. 一:基本类型 evutil_socket_t 除了Wi ...

  9. 强制去除xcode的编译警告

    使用 #pragma clang diagnostic ignored 语法来强制去除xcode的编译警告,代码举例如下: #pragma clang diagnostic push #pragma ...

  10. 线段树动态开点+树链剖分BZOJ4999

    以每个一个颜色开一颗线段树,内部以dfs序作为线段树节点,权值代表出现次数,维护线段树区间和 #include<iostream> #include<stdio.h> #inc ...