新鲜出炉!
$n leq 200000$的树,给$m leq 200000$条链,$q leq 200000$个询问,每次问一条询问链最少用m条中的几条给定链覆盖其所有边,可能无解。
首先确定一种贪心策略:$low_x$表示$x$能通过一条链跳到的最高的点(这里吐槽一下,题解描述时的树是反过来的,树根在地上!反人类啊,然后他后面所有的“高”“矮”描述全是反过来的!!!无良出题人),假设询问俩点$u,v$,lca即为$t$,那么先从$u$一直沿着$low$跳到$t$下面一点点,$v$一直沿着$low$跳到$t$下面一点点,这样的步数分别为$a$和$b$,然后答案为$a+b+2$或者$a+b+1$,取决于最后跳到那俩点是否能在一条链上。$low$的计算dfs一次就行(我TM还跑去看代码了),建出$low$的st表之后上面操作可以倍增出,现在开始$v$和$u$表示他们最后跳到比$t$下面一点点的那俩点。
现在问:一棵树好多链,每次问一个点对有没有可能在一条链上。
这不是二维数点嘛hhh,dfs序搞出来,然后如果两个询问点子树内有同个链的端点,那就存在。dfs搜一遍(第一维),搜一个点之后,先查询下他对应的另一询问点的子树(第二维),然后把这个点上的“链端点”加到树状数组,然后搜子树(第一维),然后回来再查一次另一询问点的子树(第二维),看两次查的一不一样。
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 //#include<time.h> 5 //#include<complex> 6 //#include<set> 7 //#include<queue> 8 #include<vector> 9 #include<algorithm> 10 #include<stdlib.h> 11 using namespace std; 12 13 #define LL long long 14 int qread() 15 { 16 char c; int s=0,f=1; while ((c=getchar())<'0' || c>'9') (c=='-') && (f=-1); 17 do s=s*10+c-'0'; while ((c=getchar())>='0' && c<='9'); return s*f; 18 } 19 20 //Pay attention to '-' , LL and double of qread!!!! 21 22 int n,m,lq; 23 #define maxn 200011 24 struct Edge{int to,next;}edge[maxn<<1]; int first[maxn],le=2; 25 void in(int x,int y) {Edge &e=edge[le]; e.to=y; e.next=first[x]; first[x]=le++;} 26 27 int top[maxn],dep[maxn],fa[maxn],size[maxn],ll[maxn],rr[maxn],Time=0,hea[maxn]; 28 void dfs1(int x) 29 { 30 size[x]=1; hea[x]=0; Time++; ll[x]=Time; 31 for (int i=first[x];i;i=edge[i].next) 32 { 33 Edge &e=edge[i]; 34 fa[e.to]=x; dep[e.to]=dep[x]+1; dfs1(e.to); size[x]+=size[e.to]; 35 if (size[hea[x]]<size[e.to]) hea[x]=e.to; 36 } 37 rr[x]=Time; 38 } 39 void dfs2(int x,int tt) 40 { 41 top[x]=tt; 42 if (hea[x]) dfs2(hea[x],tt); 43 for (int i=first[x];i;i=edge[i].next) if (edge[i].to!=hea[x]) dfs2(edge[i].to,edge[i].to); 44 } 45 int lca(int x,int y) 46 { 47 while (top[x]!=top[y]) 48 { 49 if (dep[top[x]]<dep[top[y]]) x^=y^=x^=y; 50 x=fa[top[x]]; 51 } 52 if (dep[x]<dep[y]) return x; return y; 53 } 54 55 int low[maxn][22]; 56 void dfslow(int x) 57 { 58 for (int i=first[x];i;i=edge[i].next) 59 { 60 Edge &e=edge[i]; dfslow(e.to); 61 low[x][0]=dep[low[x][0]]<dep[low[e.to][0]]?low[x][0]:low[e.to][0]; 62 } 63 } 64 void makelow() 65 { 66 for (int j=1;j<=18;j++) 67 for (int i=1;i<=n;i++) 68 low[i][j]=low[low[i][j-1]][j-1]; 69 } 70 71 struct Node{int x,y,t,ans;}a[maxn],q[maxn]; 72 vector<int> va[maxn],vb[maxn]; 73 void ina(int x,int y) {va[x].push_back(y);} 74 void inb(int x,int y) {vb[x].push_back(y);} 75 76 int XX; 77 int find(int x,int t) 78 { 79 if (dep[low[x][18]]>dep[t]) {XX=-0x3f3f3f3f; return -1;} 80 if (x==t) {XX=-1; return -2;} 81 int ans=0; 82 for (int j=18;~j;j--) if (dep[low[x][j]]>dep[t]) x=low[x][j],ans|=(1<<j); 83 XX=ans; return x; 84 } 85 86 struct BIT 87 { 88 int n,a[maxn]; 89 void clear(int N) {n=N;} 90 void add(int x,int v) {for (;x<=n;x+=x&-x) a[x]+=v;} 91 int query(int x) {int ans=0; for (;x;x-=x&-x) ans+=a[x]; return ans;} 92 }t; 93 int pp[maxn]; 94 void dfs(int x) 95 { 96 for (int sz=vb[x].size(),i=0;i<sz;i++) 97 { 98 int u=vb[x][i]; 99 pp[u]=t.query(rr[q[u].y])-t.query(ll[q[u].y]-1); 100 } 101 for (int sz=va[x].size(),i=0;i<sz;i++) 102 { 103 int u=va[x][i]; 104 if (x==a[u].x) t.add(ll[a[u].y],1); 105 else t.add(ll[a[u].x],1); 106 } 107 for (int i=first[x];i;i=edge[i].next) dfs(edge[i].to); 108 for (int sz=vb[x].size(),i=0;i<sz;i++) 109 { 110 int u=vb[x][i]; 111 if (t.query(rr[q[u].y])-t.query(ll[q[u].y]-1)!=pp[u]) q[u].ans--; 112 } 113 } 114 115 int main() 116 { 117 n=qread(); 118 for (int i=2,x;i<=n;i++) {x=qread(); in(x,i);} 119 dep[1]=1; dfs1(1); dfs2(1,1); 120 121 for (int i=1;i<=n;i++) low[i][0]=i; 122 m=qread(); 123 for (int i=1;i<=m;i++) 124 { 125 a[i].x=qread(); a[i].y=qread(); 126 a[i].t=lca(a[i].x,a[i].y); 127 low[a[i].x][0]=dep[low[a[i].x][0]]<dep[a[i].t]?low[a[i].x][0]:a[i].t; 128 low[a[i].y][0]=dep[low[a[i].y][0]]<dep[a[i].t]?low[a[i].y][0]:a[i].t; 129 ina(a[i].x,i); ina(a[i].y,i); 130 } 131 dfslow(1); makelow(); 132 133 lq=qread(); 134 for (int i=1;i<=lq;i++) 135 { 136 q[i].x=qread(); q[i].y=qread(); 137 q[i].t=lca(q[i].x,q[i].y); 138 q[i].ans=2; 139 int x=find(q[i].x,q[i].t); q[i].ans+=XX; 140 int y=find(q[i].y,q[i].t); q[i].ans+=XX; 141 if (x>0 && y>0) {q[i].x=x; q[i].y=y; inb(x,i);} 142 } 143 144 t.clear(n); 145 dfs(1); 146 for (int i=1;i<=lq;i++) printf("%d ",q[i].ans<0?-1:q[i].ans); 147 return 0; 148 }