[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. JavaScript 数字滚动countup.js

    1. 概述 1.1 说明 在项目过程中,有时候需要动态的去展示一些数据的加载状态,如一个数字为10000,需要5秒时间滚动加载完成.此时使用countup.js就能够很方便的处理此类功能问题. 1.2 ...

  2. MySQL数据库简单使用

    一.入门语句: 1.连接服务器: 命令:cd 安装目录\bin mysql -uroot -p 接着输入密码 ( 具体的是:mysql -u username-p password ) 远程连接MyS ...

  3. TCPThree_C杯 Day2

    T1 我已经被拉格朗日插值蒙蔽了双眼,变得智障无比. 第一反应就是拉格朗日插值,然后就先放下了它. 模数那么小,指数那么大,这是一套noip模拟题,拉格朗日,你脑袋秀逗了? 无脑暴力20分贼开心. 正 ...

  4. nodeJs学习-09 模板引擎 jade、ejs

    模板引擎: jade -破坏式.侵入式,强依赖:用了之后不能随便用别的引擎 ejs - 温和.非侵入时.弱依赖 jade使用 const jade = require('jade'); var str ...

  5. 个人总结OLinux上安装oracle11G Data Guard

    一.准备环境 1.swap要求 swap最好设置3G以上,如果安装过程中报swap不足,可参考: https://www.jianshu.com/p/46635a12c8d0 2.官网必须安装包列表: ...

  6. UDP传输对象--JavaSE考试题

    Server.java package com.sxt.udp.object; import java.io.ByteArrayInputStream; import java.io.ObjectIn ...

  7. Linus 本尊也来了!为什么 KubeCon 越来越火了?

    2015年11月,第一届 KubeCon 在美国旧金山开始的时候,还只是个200人的小会议,2019年的7月,KubeCon 第二次在中国举办,就有 3500 多位云原生和开源领域工程师齐聚一堂. 连 ...

  8. 【NS2】cygwin+NS2.29安装之道 (转载)

    最近接了一个需要进行网络模拟的项目.对与网络模拟一窍不通的本人算是一个挑战.于是乎开始整日上网搜索相关的资料,没想到这个世界的资源真是丰富多彩.最后发现了一个网络模拟的流行软件NS2,在经过多次尝试后 ...

  9. 【Leetcode链表】反转链表(206)

    题目 反转一个单链表. 示例: 输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 进阶: 你可 ...

  10. cume_dist(),允许并列名次、复制名次自动空缺,取并列后较大名次,结果如22355778……

    将score按ID分组排名:cume_dist() over(partition by id order by score desc)*sum(1) over(partition by id) 将sc ...