[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. Python多线程在爬虫中的应用

    题记:作为测试工程师经常需要解决测试数据来源的问题,解决思路无非是三种:(1)直接从生产环境拷贝真实数据 (2)从互联网上爬取数据 (3)自己用脚本或者工具造数据.前段时间,为了获取更多的测试数据,笔 ...

  2. 学习JDK1.8集合源码之--LinkedHashSet

    1. LinkedHashSet简介 LinkedHashSet继承自HashSet,故拥有HashSet的全部API,LinkedHashSet内部实现简单,核心参数和方法都继承自HashSet,只 ...

  3. 学习JDK1.8集合源码之--Stack

    1. Stack简介 Stack是集合中对数据结构栈的一种实现,栈的原则是先进先后出,与队列相反(先进先出).Stack是继承自Vector的,意味着它也是由数组实现的线程安全的,不考虑线程安全的情况 ...

  4. 开源中国 ThinkPHP 领奖

    开源中国 ThinkPHP 的领奖 周日早上早早就起来参考开源中国的活动. 由于今年竞争激烈 FastAdmin 没有上榜,但是没关系,因为这说明整个开源环境越来越好了,对于我们来说是利好. 因为 T ...

  5. 2018-12-25-Roslyn-如何使用-MSBuild-Copy-复制文件

    title author date CreateTime categories Roslyn 如何使用 MSBuild Copy 复制文件 lindexi 2018-12-25 9:35:8 +080 ...

  6. Leetcode762.Prime Number of Set Bits in Binary Representation二进制表示中质数个计算置位

    给定两个整数 L 和 R ,找到闭区间 [L, R] 范围内,计算置位位数为质数的整数个数. (注意,计算置位代表二进制表示中1的个数.例如 21 的二进制表示 10101 有 3 个计算置位.还有, ...

  7. 技巧专题3(cdq分治、整体二分等)

    cdq分治与整体二分 cdq来源于2008年国家集训队作业陈丹琦(雅礼巨佬),用一个log的代价完成从静态到动态(很多时候是减少时间那一维的). 对于一个时间段[L, R],我们取mid = (L + ...

  8. ELK学习之jdk和jre的区别

    JRE: Java Runtime EnvironmentJDK:Java Development KitJRE顾名思义是java运行时环境,包含了java虚拟机,java基础类库.是使用java语言 ...

  9. Oracle之PL/SQL编程

    PL/SQL(Procedural Language/SQL,过程语言/SQL) 是结合了Oracel过程语言和结构化查询语言(SQL)的一种扩展语言. 优点: (1)PL/SQL具有编程语言的特点, ...

  10. Nginx 外的另一选择,轻量级开源 Web 服务器 Tengine 发布新版本

    新版发布 近日,轻量级开源 Web 服务器 Tengine 发布了2.3.0版本,新增如下特性: ngx_http_proxy_connect_module,该模块让 Tengine 可以用于正向代理 ...