[WC2013]平面图-平面图点定位-学习笔记
i207M
2019-05-03 21:57:57
<见猫锟五一集训>
简单的说,就是平面图转对偶图,然后扫描线,维护线段按y排序的顺序。
~~好像跑得非常快!?~~
~~UOJ上过不了Hack#8,疑似被卡精度~~
```cpp
#pragma region
#include <bits/stdc++.h>
using namespace std;
#define ri register int
#define il inline
#define LL long long
#define uint unsigned int
#define ull unsigned long long
#define solid const auto &
#define pb push_back
#define mp make_pair
#define pii pair<int,int>
#define pll pair<LL,LL>
#define fi first
#define se second
#define gm int mid((l+r)/2)
#define space putchar(' ')
#define enter putchar('\n')
#define rd() ({ri t;in(t);t;})
#define Size(x) ((int)x.size())
#define mem(x,y) memset(x,y,sizeof(x))
template<class T>il void in(T &x)
{
x=0; char c=getchar(); bool f=0;
while(!isdigit(c)) f|=(c=='-'),c=getchar();
while(isdigit(c)) x=x*10+(c^'0'),c=getchar();
f?x=-x:0;
}
template<class T>il void out(T x,const char c='\n')
{
static short st[30]; short m=0;
if(x<0) putchar('-'),x=-x;
do st[++m]=x%10,x/=10; while(x);
while(m) putchar(st[m--]|'0');
putchar(c);
}
template<class T>il void err(const T &x,const char c='\n') {cerr<<x<<c;}
template<class T,class ...Args>il void in(T &x,Args &...args) {in(x); in(args...);}
template<class T,class ...Args>il void out(const T &x,const Args &...args) {out(x,' '); out(args...);}
template<class T,class ...Args>il void err(const T &x,const Args &...args) {err(x,' '); err(args...);}
template<class T>il void prt(T a[],int n) {for(ri i=0; i<n; ++i) out(a[i],i==n-1?'\n':' ');}
template<class T>il void clr(T a[],int n) {memset(a,0,sizeof(T)*n);}
template<class T>il void clr(T *a,T *b) {memset(a,0,sizeof(T)*(b-a));}
template<class T>il bool ckmax(T &a,const T &b) {return a<b?a=b,1:0;}
template<class T>il bool ckmin(T &a,const T &b) {return a>b?a=b,1:0;}
namespace MOD_CALC
{
const int md=1e9+7;
il int add(const int a,const int b) {return a+b>=md?a+b-md:a+b;}
il int sub(const int a,const int b) {return a-b<0?a-b+md:a-b;}
il int mul(const int a,const int b) {return (LL)a*b%md;}
il void inc(int &a,const int b) {(a+=b)>=md?a-=md:0;}
il void dec(int &a,const int b) {(a-=b)<0?a+=md:0;}
il int qpow(int a,int b) {int r=1; for(; b; b>>=1,a=mul(a,a)) if(b&1) r=mul(r,a); return r;}
il int qpow(int a,int b,const int p) {int r=1; for(; b; b>>=1,a=(LL)a*a%p) if(b&1) r=(LL)r*a%p; return r;}
il int mdinv(const int a) {return qpow(a,md-2);}
template<class ...Args>il int add(const int a,const int b,const Args &...args) {return add(add(a,b),args...);}
template<class ...Args>il int mul(const int a,const int b,const Args &...args) {return mul(mul(a,b),args...);}
} using namespace MOD_CALC;
namespace i207M
{
#pragma endregion
#define N 100005
pii wen[N]; int cq;
int ans[N];
namespace S
{
struct Edge
{
int u,v,w;
Edge() {}
Edge(const int uu,const int vv,const int ww) {u=uu,v=vv,w=ww;}
friend bool operator<(const Edge &a,const Edge &b)
{
return a.w<b.w;
}
} e[N]; int cnte;
int n;
int uf[N];
il int ufind(int x) {return x==uf[x]?x:uf[x]=ufind(uf[x]);}
vector< pii > qu[N];
void solve()
{
for(ri i=1; i<=cq; ++i)
{
if(ans[i]==-1||wen[i].fi==wen[i].se) continue;
qu[wen[i].fi].pb(mp(wen[i].se,i));
qu[wen[i].se].pb(mp(wen[i].fi,i));
}
sort(e+1,e+1+cnte);
for(ri i=1; i<=n; ++i) uf[i]=i;
for(ri i=1; i<=cnte; ++i)
{
int x=ufind(e[i].u),y=ufind(e[i].v);
if(x==y) continue;
if(Size(qu[x])>Size(qu[y])) swap(x,y);
for(solid it:qu[x])
{
if(ans[it.se]) continue;
if(ufind(it.fi)==y) ans[it.se]=e[i].w;
else qu[y].pb(it);
}
qu[x].clear();
uf[x]=y;
}
for(ri i=1; i<=cq; ++i)
if(ans[i]==-1||ufind(wen[i].fi)!=ufind(wen[i].se)) out(-1);
else out(ans[i]);
}
}
int n,m;
struct Node
{
int x,y;
Node() {}
Node(const int _x,const int _y) {x=_y,y=_y;}
friend bool operator<(const Node &a,const Node &b)
{
return a.x==b.x?a.y<b.y:a.x<b.x;
}
} pt[N];
il LL cross(const Node &a,const Node &b)
{
return (LL)a.x*b.y-(LL)a.y*b.x;
}
struct Edge
{
int v,id;
double ang;
void init(int uu,int vv,int _id)
{
v=vv,id=_id;
ang=atan2(pt[vv].y-pt[uu].y,pt[vv].x-pt[uu].x);
}
friend bool operator<(const Edge &a,const Edge &b)
{
return a.ang<b.ang;
}
} e[N*2]; int cnte=1;
int we[N];
int pos[N*2];
int visp[N],cur;
bool vise[N*2];
int eto[N*2];
bool neg[N];
LL are;
int tot;
vector<Edge>E[N];
void dfs(int x,const Edge &it)
{
if(visp[x]==cur) return;
visp[x]=cur;
are+=cross(pt[x],pt[it.v]);
vise[it.id]=1;
eto[it.id]=tot;
int k=pos[it.id^1];
if(k==0) dfs(it.v,E[it.v].back());
else dfs(it.v,E[it.v][k-1]);
}
#define eps 1e-5
double curx;
struct Line
{
int dn;
double k,b;
Line() {}
explicit Line(const int x) {b=x,k=dn=0;}
void init(int uu,int vv,int _dn)
{
dn=_dn;
k=(double)(pt[vv].y-pt[uu].y)/(pt[vv].x-pt[uu].x);
b=pt[uu].y-k*pt[uu].x;
}
friend bool operator<(const Line &a,const Line &b)
{
return a.k*curx+a.b<b.k*curx+b.b;
}
} lin[N];
pii opt[N*2]; int cnto;
void prework()
{
for(ri i=1; i<=n; ++i)
for(solid it:E[i])
{
if(vise[it.id]) continue;
are=0,++tot,++cur;
dfs(i,it);
neg[tot]=(are<0);
}
S::n=tot;
for(ri i=2; i<=cnte; i+=2)
{
if(!neg[eto[i]]&&!neg[eto[i^1]])
S::e[++S::cnte]=S::Edge(eto[i],eto[i^1],we[i>>1]);
int uu=e[i^1].v,vv=e[i].v;
if(pt[uu].x==pt[vv].x) continue;
lin[i>>1].init(uu,vv,pt[uu].x<pt[vv].x?eto[i^1]:eto[i]);
opt[++cnto]=mp(min(pt[uu].x,pt[vv].x),i>>1);
opt[++cnto]=mp(max(pt[uu].x,pt[vv].x),-(i>>1));
}
}
pair<Node,int> qu[N*2]; int cntq;
multiset<Line> st;
void solve()
{
sort(qu+1,qu+1+cntq);
sort(opt+1,opt+1+cnto);
int p=1;
for(ri i=1; i<=cntq; ++i)
{
while(p<=cnto&&opt[p].fi<=qu[i].fi.x)
{
solid it=opt[p++];
if(it.se>0)
{
curx=it.fi+eps;
st.insert(lin[it.se]);
}
else
{
curx=it.fi-eps;
st.erase(lin[-it.se]);
}
}
curx=qu[i].fi.x+eps;
auto it=st.upper_bound(Line(qu[i].fi.y));
if(it==st.end()||neg[it->dn]) ans[abs(qu[i].se)]=-1;
else if(qu[i].se>0) wen[qu[i].se].fi=it->dn;
else wen[-qu[i].se].se=it->dn;
}
}
signed main()
{
#ifdef M207
freopen("in.in","r",stdin);
// freopen("ot.out","w",stdout);
#endif
in(n,m);
for(ri i=1; i<=n; ++i) in(pt[i].x,pt[i].y),pt[i].x<<=1,pt[i].y<<=1;
for(ri i=1,a,b; i<=m; ++i)
{
in(a,b,we[i]);
++cnte,e[cnte].init(a,b,cnte);
E[a].pb(e[cnte]);
++cnte,e[cnte].init(b,a,cnte);
E[b].pb(e[cnte]);
}
for(ri i=1; i<=n; ++i)
{
sort(E[i].begin(),E[i].end());
for(ri j=0; j<Size(E[i]); ++j) pos[E[i][j].id]=j;
}
in(cq);
for(ri i=1; i<=cq; ++i)
{
static double a,b;
scanf("%lf%lf",&a,&b);
qu[++cntq].fi.x=a*2,qu[cntq].fi.y=b*2;
qu[cntq].se=i;
scanf("%lf%lf",&a,&b);
qu[++cntq].fi.x=a*2,qu[cntq].fi.y=b*2;
qu[cntq].se=-i;
}
prework();
solve();
S::solve();
return 0;
}
#pragma region
}
signed main()
{
i207M::main();
return 0;
}
#pragma endregion
```