在線、可持久化地維護一條二維平面上的折線,支持查詢與任意一條直線的交點個數。
點的個數和操做個數小於\(10^5\)node
一條折線能夠用一個序列表示,可持久化序列考慮用可持久化treap。
如何判斷交點?若是有交點,那麼必定與包含這個折線的矩陣有交點。c++
因此咱們可持久化treap一下便可,雖然這個複雜度很不靠譜,純rp算法。算法
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int Lim=20000000, M=1e5+10, oo=~0u>>1; struct node *null; struct node { int x, y, s, mx[2], mn[2]; node *c[2], *ch[2]; void up() { s=c[0]->s+c[1]->s+1; mx[0]=max(x, max(c[0]->mx[0], c[1]->mx[0])); mn[0]=min(x, min(c[0]->mn[0], c[1]->mn[0])); mx[1]=max(y, max(c[0]->mx[1], c[1]->mx[1])); mn[1]=min(y, min(c[0]->mn[1], c[1]->mn[1])); if(c[0]!=null) ch[0]=c[0]->ch[0]; else ch[0]=this; if(c[1]!=null) ch[1]=c[1]->ch[1]; else ch[1]=this; } void init(int _x, int _y) { x=mx[0]=mn[0]=_x; y=mx[1]=mn[1]=_y; c[0]=c[1]=null; ch[0]=ch[1]=this; s=1; } }Po[Lim], *iT=Po, *t[M]; node *newnode(int x, int y) { iT->init(x, y); return iT++; } void init() { null=iT++; null->init(0, 0); null->mx[0]=null->mx[1]=-oo; null->mn[0]=null->mn[1]=oo; null->s=0; } node *build(int l, int r) { if(l>r) { return null; } node *ret; int x, y, mid=(l+r)>>1; node *le=build(l, mid-1); scanf("%d%d", &x, &y); node *ri=build(mid+1, r); ret=newnode(x, y); ret->c[0]=le; ret->c[1]=ri; ret->up(); return ret; } node *update(int p, int X, int Y, node *x) { node *y; if(x->s==p) { y=newnode(X, Y); y->c[0]=x; y->up(); return y; } y=iT++; *y=*x; if(y->c[0]->s>=p) { y->c[0]=update(p, X, Y, y->c[0]); } else { y->c[1]=update(p-y->c[0]->s-1, X, Y, y->c[1]); } y->up(); return y; } ll cross(int x0, int y0, int x, int y) { return (ll)x0*y-(ll)x*y0; } bool jiao(int x, int y, int xx, int yy, int x0, int y0, int X, int Y) { ll a=cross(x-x0, y-y0, X, Y), b=cross(xx-x0, yy-y0, X, Y); a=a>=0?a>0:-1; b=b>=0?b>0:-1; return a*b<=0; } bool jiao(node *x, int x0, int y0, int X, int Y) { return jiao(x->mn[0], x->mx[1], x->mn[0], x->mn[1], x0, y0, X, Y) || jiao(x->mn[0], x->mn[1], x->mx[0], x->mn[1], x0, y0, X, Y) || jiao(x->mx[0], x->mn[1], x->mx[0], x->mx[1], x0, y0, X, Y) || jiao(x->mx[0], x->mx[1], x->mn[0], x->mx[1], x0, y0, X, Y); } int query(int x0, int y0, int X, int Y, node *x) { if(x->s<=1 || !jiao(x, x0, y0, X, Y)) { return 0; } int ret=0; if(x->c[0]!=null && jiao(x->x, x->y, x->c[0]->ch[1]->x, x->c[0]->ch[1]->y, x0, y0, X, Y)) { ++ret; } if(x->c[1]!=null && jiao(x->x, x->y, x->c[1]->ch[0]->x, x->c[1]->ch[0]->y, x0, y0, X, Y)) { ++ret; } return query(x0, y0, X, Y, x->c[0])+query(x0, y0, X, Y, x->c[1])+ret; } int main() { init(); int n, m, cn, last=0; scanf("%d%d%d", &n, &m, &cn); t[0]=build(1, n); for(int kk=1; kk<=m; ++kk) { static char s[5]; int T, x0, y0, x, y; scanf("%s", s); if(s[0]=='H') { scanf("%d%d%d%d%d", &T, &x0, &y0, &x, &y); if(cn) { x0^=last; y0^=last; x^=last; y^=last; } t[kk]=t[T]; printf("%d\n", last=query(x0, y0, x, y, t[kk])); } else { scanf("%d%d%d%d", &T, &x0, &x, &y); if(cn) { x^=last; y^=last; } t[kk]=update(x0, x, y, t[T]); } } return 0; }