$n leq 500000$的树给$m leq 500000$个路径,$q leq 500000$个询问每次问一个区间的路径交。
路径交口诀:(前方高能)
判有交,此链有彼祖;
取其交,最深两两祖。
说成人话就是:判两条路径有没有交,只要一条链的lca在另一条链上就一定有交;取两条路径的交,把两条路径的端点两两求出四对lca,最深那两个就是路径交。
证明?我会还用口诀!
由于需要很多很多次查lca,这里用欧拉序+st表求。查区间路径交可以线段树也可以st表,毕竟重复的部分算两次没问题。
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 //#include<time.h> 6 //#include<complex> 7 #include<algorithm> 8 #include<stdlib.h> 9 using namespace std; 10 11 int n,m,q; 12 #define maxn 500011 13 struct Edge{int to,next,v;}edge[maxn<<1]; int first[maxn],le=2; 14 void in(int x,int y,int v) {Edge &e=edge[le]; e.to=y; e.v=v; e.next=first[x]; first[x]=le++;} 15 void insert(int x,int y,int v) {in(x,y,v); in(y,x,v);} 16 17 int len,dep[maxn],id[maxn],st[maxn<<1][22],Log[maxn<<1]; 18 #define LL long long 19 LL dis[maxn]; 20 void dfs(int x,int fa) 21 { 22 st[++len][0]=x; id[x]=len; dep[x]=dep[fa]+1; 23 for (int i=first[x];i;i=edge[i].next) 24 { 25 Edge &e=edge[i]; if (e.to==fa) continue; 26 dis[e.to]=dis[x]+e.v; dfs(e.to,x); st[++len][0]=x; 27 } 28 } 29 30 void makest() 31 { 32 Log[0]=-1; for (int i=1;i<=len;i++) Log[i]=Log[i>>1]+1; 33 for (int j=1;j<=20;j++) 34 for (int i=1,to=len-(1<<j)+1;i<=to;i++) 35 st[i][j]=dep[st[i][j-1]]<dep[st[i+(1<<(j-1))][j-1]]?st[i][j-1]:st[i+(1<<(j-1))][j-1]; 36 } 37 38 int lca(int x,int y) 39 { 40 if (id[x]>id[y]) {int t=x;x=y;y=t;} x=id[x]; y=id[y]; 41 int l=Log[y-x+1]; 42 return dep[st[x][l]]<dep[st[y-(1<<l)+1][l]]?st[x][l]:st[y-(1<<l)+1][l]; 43 } 44 45 struct Line{int x,y;}line[maxn]; 46 bool cmpdep(const int a,const int b) {return dep[a]<dep[b];} 47 Line combine(Line a,Line b) 48 { 49 if (a.x==-1 || b.x==-1) return (Line){-1,-1}; 50 int l1=lca(a.x,a.y),l2=lca(b.x,b.y); 51 int t1=lca(l1,b.x),t2=lca(l1,b.y),t3=lca(a.x,l2),t4=lca(a.y,l2); 52 bool flag=0; 53 if ((t1==l1 && dep[t1]>=dep[l2]) || (t2==l1 && dep[t2]>=dep[l2])) flag=1; 54 if ((t3==l2 && dep[t3]>=dep[l1]) || (t4==l2 && dep[t4]>=dep[l1])) flag=1; 55 if (!flag) return (Line){-1,-1}; 56 int d[5]; d[0]=lca(a.x,b.x); d[1]=lca(a.x,b.y); d[2]=lca(a.y,b.x); d[3]=lca(a.y,b.y); 57 sort(d,d+4,cmpdep); return (Line){d[2],d[3]}; 58 } 59 60 struct SMT 61 { 62 struct Node 63 { 64 int ls,rs; 65 Line com; 66 }a[maxn<<1]; 67 int size,n; 68 void clear(int m) {size=0; n=m;} 69 void up(int x) 70 { 71 int &p=a[x].ls,&q=a[x].rs; 72 a[x].com=combine(a[p].com,a[q].com); 73 } 74 void build(int &x,int L,int R) 75 { 76 x=++size; 77 if (L==R) {a[x].com=line[L]; a[x].ls=a[x].rs=0; return;} 78 int mid=(L+R)>>1; 79 build(a[x].ls,L,mid); build(a[x].rs,mid+1,R); up(x); 80 } 81 void build() {int x; build(x,1,n);} 82 int ql,qr; 83 Line Query(int x,int L,int R) 84 { 85 if (ql<=L && R<=qr) return a[x].com; 86 int mid=(L+R)>>1; Line ans; bool flag=0; 87 if (ql<=mid) ans=Query(a[x].ls,L,mid),flag=1; 88 if (qr>mid) {if (flag) ans=combine(Query(a[x].rs,mid+1,R),ans); else ans=Query(a[x].rs,mid+1,R);} 89 return ans; 90 } 91 Line query(int L,int R) {ql=L; qr=R; return Query(1,1,n);} 92 }t; 93 94 int main() 95 { 96 scanf("%d",&n); 97 for (int i=1,x,y,v;i<n;i++) scanf("%d%d%d",&x,&y,&v),insert(x,y,v); 98 len=0; dfs(1,0); makest(); 99 scanf("%d",&m); 100 for (int i=1;i<=m;i++) scanf("%d%d",&line[i].x,&line[i].y); 101 t.clear(m); t.build(); 102 scanf("%d",&q); 103 while (q--) 104 { 105 int x,y; scanf("%d%d",&x,&y); 106 Line ans=t.query(x,y); 107 printf("%lld ",dis[ans.x]+dis[ans.y]-2*dis[lca(ans.x,ans.y)]); 108 } 109 return 0; 110 }