P3316 [SDOI2014] 里面还是外面
\lxl/\lxl/
判断一个点是否在多边形内通常的做法是引一条射线,算出交点个数奇偶性。
那么我们就可以令这条射线平行于\(y\)轴,现在只用快速算出这样的交点数就好了。
考虑将多边形的每条边抽离。按\(x\)坐标建立线段树后,将线段插入到\(O(\log n)\)个线段树节点上,这样每个节点所代表的\(x\)坐标区间内,线段都是贯穿的,并且不相交(除了顶点)。
因为我们要支持查询某个\(x=P\)直线与若干线段交点中,纵坐标\(\le K\)的个数,线段需要带修,所以我们对每个线段树节点开一棵平衡树维护插入、删除、查排名操作就好了。
PEKKA说要用vector写平衡树,确实能冲。
代码:
#include<bits/stdc++.h>
#define db long double
using namespace std;
using ll=long long;
char *p1,*p2,buf[100000];
#define gc() (p1==p2 && (p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
inline int read(){
int x=0,f=1;char c=gc();
for(;c<'0'||c>'9';c=gc())if(c=='-')f=-1;
for(;c>='0'&&c<='9';c=gc())x=(x<<1)+(x<<3)+c-'0';
return x*f;
}
const int N=2e5+5;
const int INF=1e9,V=1e9;
int n,q;
struct Point{
int x,y;
}p[N];
int pcnt,lcnt;
unordered_map<ll,int>um_p,um_l;
struct Line{
Point st,ed;
Line(){}
Line(Point ps,Point pd){
st=ps,ed=pd;
if(st.x>ed.x)swap(st,ed);
}
inline db gt(int pos){
db k=1.0*(ed.y-st.y)/(ed.x-st.x);
db b=ed.y-k*ed.x;
return pos*k+b;
}
inline bool bon(int x,int y){
if(x<st.x||x>ed.x)return 0;
return 1ll*(st.x-x)*(ed.y-st.y)==1ll*(ed.x-st.x)*(st.y-y);
}
}li[N];
inline ll ghas(int x,int y){return 1ll*(INF+1)*x+y;}
inline int gpo(int x,int y){return um_p[ghas(x,y)];}
inline int glin(int x,int y){if(x>y)swap(x,y);return um_l[ghas(x,y)];}
bool mbo;
struct V_Treap{
int lp,rp;
struct pnod{
int id,pos;
inline bool operator <(const pnod P){return li[id].gt(pos)<li[P.id].gt(pos);}
};
inline void init(int pl,int pr){lp=pl,rp=pr;}
vector<pnod>tr;
inline void ins(int x){
tr.insert(lower_bound(tr.begin(),tr.end(),(pnod){x,lp}),{x,lp});
}
inline void era(int x){
tr.erase(lower_bound(tr.begin(),tr.end(),(pnod){x,lp}));
}
inline int qry(int x,int y){
if(tr.empty())return 0;
int l=0,r=(int)tr.size()-1;
while(l<=r){
int mid=(l+r)>>1;
if(li[tr[mid].id].bon(x,y)){
mbo=1;
return 0;
}
if(li[tr[mid].id].gt(x)-1e-9<=y)l=mid+1;
else r=mid-1;
}
return l;
}
}trp[N<<6];
struct node{
int ls,rs;
}tr[N<<6];
int cnt;
struct SGT{
#define ls(p) tr[p].ls
#define rs(p) tr[p].rs
int rt;
void upd(int &p,int l,int r,int x,int y,int v,int w){
if(!p)p=++cnt,trp[p].init(l,r);
if(x<=l&&r<=y)return w==1?trp[p].ins(v):trp[p].era(v);
if(r==l+1)return ;
int mid=(l+r)>>1;
if(x<=mid)upd(ls(p),l,mid,x,y,v,w);
if(y>=mid)upd(rs(p),mid,r,x,y,v,w);
}
inline void ins(int v){return upd(rt,0,V,li[v].st.x,li[v].ed.x,v,1);}
inline void del(int v){return upd(rt,0,V,li[v].st.x,li[v].ed.x,v,-1);}
int qry(int p,int l,int r,int x,int y){
if(l>x||r<x)return 0;
if(!p)return 0;
if(l==r)return trp[p].qry(x,y);
int res=trp[p].qry(x,y),mid=(l+r)>>1;
res+=qry(ls(p),l,mid,x,y);
res+=qry(rs(p),mid,r,x,y);
return res;
}
inline int qry(int x,int y){return qry(rt,0,V,x,y);}
}T;
inline string to(int x){
if(x==1)return "in";
if(x==0)return "out";
return "bd";
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
n=read();
for(int i=1;i<=n;i++){
p[i].x=read(),p[i].y=read();
um_p[ghas(p[i].x,p[i].y)]=i;
}
for(int i=1;i<=n;i++){
int nxt=i%n+1;
um_l[ghas(min(i,nxt),max(i,nxt))]=i;
li[i]=Line(p[i],p[i%n+1]);
T.ins(i);
}
int las=T.qry(0,0)&1;
if(mbo==1)las=2;
pcnt=lcnt=n;
int lasx=0,lasy=0;
q=read();
int op,r,xa,ya,xb,yb,xc,yc,x,y;
for(int i=1;i<=q;i++){
mbo=0;
op=read();
if(op==0){
r=read(),xa=read(),ya=read(),xb=read(),yb=read(),xc=read(),yc
=read();
if(las==1){
x=(r*lasx+xa)%V;
y=(r*lasy+ya)%V;
}
else if(las==0){
x=(r*lasx+xb)%V;
y=(r*lasy+yb)%V;
}
else{
x=(r*lasx+xc)%V;
y=(r*lasy+yc)%V;
}
lasx=x,lasy=y;
las=T.qry(x,y);
las&=1;
if(mbo==1)las=2;
cout<<to(las)<<"\n";
}
else{
xa=read(),ya=read(),xb=read(),yb=read(),xc=read(),yc
=read();
int ia=gpo(xa,ya),ib=gpo(xb,yb);
p[++pcnt]={xc,yc};
um_p[ghas(xc,yc)]=pcnt;
int &v=um_l[ghas(min(ia,ib),max(ia,ib))];
T.del(v);v=0;
li[++lcnt]=Line(p[ia],p[pcnt]),um_l[ghas(ia,pcnt)]=lcnt,T.ins(lcnt);
li[++lcnt]=Line(p[ib],p[pcnt]),um_l[ghas(ib,pcnt)]=lcnt,T.ins(lcnt);
}
}
return 0;
}

浙公网安备 33010602011771号