\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].rsint 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;
}