Let's say d[x]<d[y in the two-point question].
If X is the ancestor of Y, then it is the number of hops from the first point in the X-to-y direction, and the ending point in the y subtree.
If x is not the ancestor of Y, then it is the number of jumping points in the X subtree and the end point in the Y subtree.
The use of Dfs sequence can be converted to a rectangle, so the use of CDQ + scan line + Tree array can be done $o (N\LOG^2N) $.
#include <cstdio> #include <algorithm> #define N 200010using namespace Std;int n,m,q,i,op,x,y,t,pos[n],bit[ N],ans[n],cb,cc;int g[n],v[n],nxt[n],ed,f[n],size[n],son[n],top[n],d[n],st[n],en[n],dfn;struct P{int x,y,t; P () {}p (int _x,int _y,int _t) {x=_x,y=_y,t=_t;}} a[n],b[n];inline bool CMPB (const P&a,const p&b) {return a.x<b.x;} struct C{int x,l,r,t,p; C () {}c (int _x,int _l,int _r,int _t,int _p) {x=_x,l=_l,r=_r,t=_t,p=_p;}} c[n];inline bool CMPC (const C&a,const c&b) {return a.x<b.x;} inline void Read (int&a) {char c;while (!) ( ((C=getchar ()) >= ' 0 ') && (c<= ' 9 ')); a=c-' 0 '; while (((C=getchar ()) >= ' 0 ') && (c<= ' 9 ')) (a*= Ten) +=c-' 0 ';} inline void Add (int x,int y) {v[++ed]=y;nxt[ed]=g[x];g[x]=ed;} void Dfs (int x) {size[x]=1; for (int i=g[x];i;i=nxt[i]) if (V[i]!=f[x]) {D[v[i]]=d[f[v[i]]=x]+1;dfs (v[i]); Size[x]+=size[v[i]]; if (Size[v[i]]>size[son[x]]) son[x]=v[i]; }}void dfs2 (int x,int y) {st[x]=++dfn;top[x]=y; if (Son[x]) DFS2 (son[x],y); for (int i=g[x];I;i=nxt[i]) if (v[i]!=son[x]&&v[i]!=f[x]) DFS2 (V[i],v[i]); EN[X]=DFN;} inline int lca2 (int x,int y) {int t; while (Top[x]!=top[y]) t=top[y],y=f[top[y]]; return x==y?t:son[x];} inline void ins (int x,int y) {for (; x<=n;x+=x&-x) if (pos[x]<t) Pos[x]=t,bit[x]=y;else bit[x]+=y;} inline int Ask (int x) {int t=0;for (; x;x-=x&-x) if (pos[x]==t) T+=bit[x];return t;} void Solve (int l,int r) {if (l==r) return; int mid= (L+R) >>1; Solve (L,mid), Solve (mid+1,r); int i,j; cb=cc=0; for (i=l;i<=mid;i++) {if (a[i].t<0) {b[cb++]=p (a[i].x,a[i].y,-1); B[cb++]=p (a[i].y,a[i].x,-1); } if (!a[i].t) {b[cb++]=p (a[i].x,a[i].y,1); B[cb++]=p (a[i].y,a[i].x,1); }} if (!CB) return; for (i=r;i>mid;i--) {if (a[i].t==1) {c[cc++]=c (n,st[a[i].y],en[a[i].y],1,i); C[cc++]=c (St[a[i].x]-1,st[a[i].y],en[a[i].y],1,i); C[cc++]=c (En[a[i].x],st[a[i].y],en[a[i].y],-1,i); } if (a[i].t==2) {c[cc++]=c (st[a[i].x]-1,st[a[i].y],en[a[i].y],-1,i); C[cc++]=c (En[a[i].x],st[a[i].y],en[a[i].y],1,i); }} if (!CC) return; if (cb>1) sort (B,B+CB,CMPB); if (cc>1) sort (C,C+CC,CMPC); for (t++,i=j=0;i<cc;i++) {while (j<cb&&b[j].x<=c[i].x) ins (b[j].y,b[j].t), j + +; ans[c[i].p]+=c[i].t* (Ask (C[I].R)-ask (C[I].L-1)); }}int Main () {read (n); for (i=1;i<n;i++) read (x), read (y), add (x, y), add (y,x); DFS (1), DFS2 (+); Read (q); while (q--) read (x), read (y), a[++m]=p (st[x],st[y],0); Read (q); while (q--) {Read (OP), read (x), read (y); if (op==1) a[++m]=p (st[x],st[y],0); if (op==2) a[++m]=p (st[x],st[y],-1); if (op==3) {if (D[x]>d[y]) swap (x, y); if (St[x]<=st[y]&&en[y]<=en[x]) a[++m]=p (LCA2 (x, y), y,1); else a[++m]=p (x,y,2); }} solve (1,m); for (i=1;i<=m;i++) if (a[i].t>0) printf ("%d\n", Ans[i]); return 0;}
BZOJ4285: Messenger