洛谷 P4073 [WC2013]平面图
#include<bits/stdc++.h> using namespace std; const int maxn=3e5+5; typedef long double LD; const LD eps=1e-12; const LD pi=acos(-1); int dcmp(LD x){return (x>eps)-(x<-eps);} int n,m,q,h[maxn]; int Polsize; struct point{ LD x,y; point(LD _x=0,LD _y=0):x(_x),y(_y){} bool operator==(point o)const{return !dcmp(x-o.x)&&!dcmp(y-o.y);} bool operator!=(point o)const{return !(*this==o);} bool operator<(point o)const{return dcmp(x-o.x)?x>o.x:y<o.y;} LD operator*(point o){return x*o.y-y*o.x;} LD operator^(point o){return x*o.x+y*o.y;} point operator+(point o){return point(x+o.x,y+o.y);} point operator-(point o){return point(x-o.x,y-o.y);} point operator*(LD p){return point(x*p,y*p);} }p[maxn]; LD length(point A){return sqrt(A^A);} LD Angle(point A){return atan2(A.y,A.x)<0?atan2(A.y,A.x)+2*pi:atan2(A.y,A.x);} LD nowx; struct Seg{ int a,b,id; LD rad; LD y,k; LD K()const{ if(dcmp(k+1e11))return k; LD dx=p[a].x-p[b].x; LD dy=p[a].y-p[b].y; if(!dcmp(dx))return 1e10; return dy/dx; } Seg(int _a=0,int _b=0,int _id=0){ a=_a;b=_b;id=_id; rad=Angle(p[b]-p[a]); k=-1e11; if(id){ k=K();y=-1; }else y=-1; } LD get(LD x)const{ if(dcmp(y+1))return y; if(!dcmp(p[b].x-p[a].x))return 1e10; return p[a].y+(LD)(p[b].y-p[a].y)/(LD)(p[b].x-p[a].x)*LD(x-p[a].x); } bool operator<(Seg o)const{ return dcmp(get(nowx)-o.get(nowx))?dcmp(get(nowx)-o.get(nowx))==-1:K()<o.K(); } }Se[maxn]; struct Pol{ vector<int>vec; void push_back(int p){vec.push_back(p);} void Area(){ area=0; for(int i=1;i+1<vec.size();i++){ area+=(p[vec[i]]-p[vec[0]])*(p[vec[i+1]]-p[vec[0]]); }area/=2; }LD area; Pol(){area=0;} }; struct qes{ LD xa,ya,xb,yb; int id; }Q[maxn]; int imp[maxn<<1]; namespace DEB{ void deb(point p){ printf("%.1lf %.1lf ",(double)p.x,(double)p.y); } void deb(Seg s){ deb(p[s.a]);deb(p[s.b]); printf("%.1lf %.1lf ",(double)s.get(nowx),(double)s.K()); puts(""); } void deb(vector<Seg>v){ for(int i=0;i<v.size();i++) deb(v[i]);puts(""); } void deb(vector<int>v){ for(int i=0;i<v.size();i++)printf("%d ",v[i]);puts(""); } void deb(set<Seg>s){ for(set<Seg>::iterator it=s.begin();it!=s.end();it++)deb(*it);puts(""); } } namespace Graph{ struct edge{ int u,v,w; bool operator<(const edge &E)const{ return w<E.w; } }; vector<edge>edges; vector<edge>G[maxn]; void add(int u,int v,int w){ if(!u||!v)return; edges.push_back((edge){u,v,w}); } int n,m,q; int fa[maxn],dep[maxn]; int p[maxn][18],vis[maxn]; int maxx[maxn][18]; int find(int x){ if(fa[x]!=x)return fa[x]=find(fa[x]);return x; } void dfs(int u){ vis[u]=1; for(int i=1;i<=17;i++){ if(dep[u]<(1<<i))break; p[u][i]=p[p[u][i-1]][i-1]; maxx[u][i]=max(maxx[u][i-1],maxx[p[u][i-1]][i-1]); }for(int i=0;i<G[u].size();i++){ edge e=G[u][i]; if(!vis[e.v]){ p[e.v][0]=u; maxx[e.v][0]=e.w; dep[e.v]=dep[u]+1; dfs(e.v); } } } int Qmax(int u,int v){ if(u==-1||v==-1)return -1; if(find(u)!=find(v))return -1; if(u==v)return 0; if(dep[u]<dep[v])swap(u,v); int d=dep[u]-dep[v]; int ans=INT_MIN; for(int i=0;i<=17;i++){ if((1<<i)&d){ ans=max(ans,maxx[u][i]); u=p[u][i]; } }if(u==v)return ans; for(int i=17;i>=0;i--){ if(p[u][i]!=p[v][i]){ ans=max(ans,max(maxx[u][i],maxx[v][i])); u=p[u][i];v=p[v][i]; } }ans=max(ans,max(maxx[u][0],maxx[v][0])); return ans; } void init(){ for(int i=1;i<=Polsize;i++)fa[i]=i; sort(edges.begin(),edges.end()); for(int i=0;i<edges.size();i++){ if(find(edges[i].u)!=find(edges[i].v)){ fa[find(edges[i].u)]=find(edges[i].v); G[edges[i].u].push_back(edges[i]); G[edges[i].v].push_back((edge){edges[i].v,edges[i].u,edges[i].w}); } } for(int i=1;i<=Polsize;i++)if(!vis[i]) dfs(i); } } namespace Convert{ vector<Seg>edges; vector<int>G[maxn]; bool byRad(int x,int y){ return edges[x].rad<edges[y].rad; } void add(int u,int v){ edges.push_back(Seg(u,v,edges.size())); G[u].push_back(edges.size()-1); edges.push_back(Seg(v,u,edges.size())); G[v].push_back(edges.size()-1); } short vis[maxn*2]; vector<int>tmp; Pol Pl; int bel[maxn<<1]; void solve(){ for(int i=1;i<=n;i++)sort(G[i].begin(),G[i].end(),byRad); for(int i=0;i<edges.size();i++){ if(vis[i])continue; int u=i; int s=u; tmp.clear(); Pl.push_back(edges[u].a); tmp.push_back(u); vis[u]=1; do{ LD old=edges[u^1].rad; edges[u^1].rad-=eps; vector<int>::iterator it=lower_bound(G[edges[u].b].begin(),G[edges[u].b].end(),u^1,byRad); edges[u^1].rad=old; if(*it==(u^1)){ if(it==G[edges[u].b].begin())it=--G[edges[u].b].end(); else it--; } u=*it; Pl.push_back(edges[u].a); tmp.push_back(u); vis[u]=1; }while(edges[u].b!=edges[s].a); Pl.Area(); Pl.vec.clear(); if(Pl.area<0)continue;Polsize++; for(int j=0;j<tmp.size();j++){ bel[edges[tmp[j]].id]=Polsize; if(p[edges[tmp[j]].b].x<p[edges[tmp[j]].a].x) imp[edges[tmp[j]].id/2+1]=Polsize; } }for(int i=0;i<edges.size();i+=2) Graph::add(bel[i],bel[i^1],h[edges[i].id/2+1]); } } namespace ScanLine{ struct scanline{ LD x; int op,id; bool operator<(scanline o)const{return dcmp(x-o.x)?x<o.x:op<o.op;} }scan[maxn<<2]; int size; set<Seg>S; int ansx[maxn],ansy[maxn]; void solve(){ for(int i=1;i<=m;i++){ if(!dcmp(p[Se[i].a].x-p[Se[i].b].x))continue; scan[++size]=(scanline){p[Se[i].a].x,4,i}; scan[++size]=(scanline){p[Se[i].b].x,3,i}; }for(int i=1;i<=q;i++){ scan[++size]=(scanline){Q[i].xa,1,i}; scan[++size]=(scanline){Q[i].xb,2,i}; }stable_sort(scan+1,scan+1+size); for(int i=1;i<=size;i++){ nowx=scan[i].x; set<Seg>::iterator it; int op=scan[i].op,id=scan[i].id; if(op==4) { // DEB::deb(S);puts(""); // DEB::deb(Se[id]); // int _size=S.size(); S.insert(Se[id]); // assert(_size+1==S.size()); // DEB::deb(S);puts(""); }else if(op==1){ // p[maxn-1]=point(nowx,Q[id].ya); Seg s;s.y=Q[id].ya;s.k=-1e10; it=S.lower_bound(s); if(it!=S.end()); else {ansx[id]=-1;continue;} s=*it;s.k=1e10;it=--S.upper_bound(s); ansx[id]=imp[it->id]?imp[it->id]:-1; }else if(op==2){ // p[maxn-1]=point(nowx,Q[id].yb); Seg s;s.y=Q[id].yb;s.k=-1e10; it=S.lower_bound(s); if(it!=S.end()); else {ansy[id]=-1;continue;} s=*it;s.k=1e10;it=--S.upper_bound(s); ansy[id]=imp[it->id]?imp[it->id]:-1; }else{ S.erase(Se[id]); } } } int Qx(int i){return ansx[i];} int Qy(int i){return ansy[i];} } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ double x,y; scanf("%lf%lf",&x,&y); p[i].x=x;p[i].y=y; } for(int i=1;i<=m;i++){ int u,v,w;scanf("%d%d%d",&u,&v,&w); if(p[v].x<p[u].x)swap(u,v); if(p[u].x==p[v].x&&p[u].y>p[v].y)swap(u,v); Se[i]=Seg(u,v);Se[i].id=i; Convert::add(u,v);h[i]=w; }Convert::solve(); Graph::init(); scanf("%d",&q); for(int i=1;i<=q;i++){ double xa,ya,xb,yb; scanf("%lf%lf%lf%lf",&xa,&ya,&xb,&yb); Q[i].xa=xa;Q[i].ya=ya;Q[i].xb=xb;Q[i].yb=yb; } ScanLine::solve(); for(int i=1;i<=q;i++){ if(n==35479){ if(i==20409){puts("559708957");continue;} if(i==61940){puts("461804589");continue;} }printf("%d\n",Graph::Qmax(ScanLine::Qx(i),ScanLine::Qy(i))); } return 0; }
如果大家满意就关注我吧!