the
Given a tree of n nodes, there is a number on each node.
M times inquiry, there are several different numbers on the path to V. Solving
The classic problem of Mo team in the tree.
First of all, the tree will be divided into pieces, see bzoj1086: [SCOI2005] Royal Commonwealth.
Similar to the Common Mo Team, remember Dfn[x] for X's into the stack timestamp, we press (Belong[u], dfn[v]) to sort all inquiries.
Obviously the furthest point of the same block after the block is not more than the size of the block,
And considering the bracket sequence, dfn[v] increments the words one step at a time without exceeding the 2n part.
So the complexity is similar to that of the common Mo team.
How to move from the current state to the next. You can see that the point of LCA is a little special.
For this question, if we get other information besides the LCA, we need to add the LCA point to the answer.
Set S (u,v) removes the information of the LCA point from the path from U to V, and T (x) represents the information from the root to the X.
If we change V to V2, consider which of the changes (the following plus is a similar operation, that is, 2 of the same elements will be lost):
S (u,v) +s (U,V2) s (u,v) + S (u,v_2)
= (t (u) +t (v) + (t (u) +t (v2)) = (t (u) + t (v) + (t (u) + t (v_2))
= (T (v) +t (v2)) =s (V,V2) = (T (v) + t (v_2)) =s (v,v_2)
In other words, only the existence of the point of LCA (V,V2) can be reversed in the path of V to v2.
Complexity O (nn−−√) O (n\sqrt N)
#include <cstdio> #include <cmath> #include <algorithm> using namespace std;
const int maxn=40005, maxe=80005, maxq=100005;
int N,M,C[MAXN],B[MAXN],SUM[MAXN],ANS,DFN[MAXN],TIM,G,BLK,BLG[MAXN],STK[MAXN],TOP,ID_C[MAXN];
int Son[maxe],fir[maxn],nxt[maxe],tot;
BOOL VIS[MAXN];
int dfs (int x,int pre) {dfn[x]=++tim; int bottom=top;
for (int j=fir[x];j;j=nxt[j]) if (son[j]!=pre) {DFS (son[j],x);
if (top-bottom>=blk) {g++;
while (Top!=bottom) blg[stk[top--]]=g;
}} stk[++top]=x;
} struct data{int x,y,id,res;} Q[MAXQ];
BOOL My_cmp1 (const data &a,const data &b) {if (blg[a.x]==blg[b.x)) return dfn[a.y]<dfn[b.y];
Return blg[a.x]<blg[b.x]; BOOL MY_CMP2 (const data &a,const data &b) {return a.id<b.id;} void Add (int x,int y) {son[++tot]=y; nxt[t OT]=FIR[X];
Fir[x]=tot;
int ANC[MAXN][20],DEP[MAXN]; void Dfs_lca (int x,int pre) {anc[x][0]=pre for (int i=1;i<=17;i++) anc[x][i]=anc[aNC[X][I-1]][I-1];
for (int j=fir[x];j;j=nxt[j]) if (son[j]!=pre) dep[son[j]]=dep[x]+1, Dfs_lca (son[j],x);
int LCA (int x,int y) {if (Dep[x]<dep[y]) swap (x,y);
for (int j=17;j>=0;j--) if (Dep[anc[x][j]]>=dep[y]) x=anc[x][j];
if (x==y) return x;
for (int j=17;j>=0;j--) if (Anc[x][j]!=anc[y][j]) x=anc[x][j], y=anc[y][j];
return anc[x][0];
int find (int x) {int l=1,r=b[0];
while (l<=r) {int mid= (L+R) >>1;
if (b[mid]==x) return mid; if (b[mid]<x) l=mid+1;
else r=mid-1;
} void Rev (int x) {if (vis[x]) ans= (--sum[id_c[x])? ans:ans-1;
else ans= (sum[id_c[x]]++)? ans:ans+1;
Vis[x]^=1;
} void work (int x,int y) {while (x!=y) {if (dep[x]<dep[y)) swap (x,y); Rev (x);
X=ANC[X][0];
int main () {freopen ("cot2.in", "R", stdin);
Freopen ("Cot2.out", "w", stdout);
scanf ("%d%d", &n,&m);
for (int i=1;i<=n;i++) scanf ("%d", &c[i]), b[++b[0]]=c[i]; for (int i=1;i<=n-1;i++) {int x,y; scanf ("%d%d", &x,&y); Add (x,y);
Add (y,x);
} DFS_LCA (1,1); BLK=SQRT (n);
DFS (1,0);
for (int i=1;i<=m;i++) {scanf ("%d%d", &q[i].x,&q[i].y); q[i].id=i;
if (Dfn[q[i].x]>dfn[q[i].y]) swap (Q[I].X,Q[I].Y); Sort (b+1,b+1+b[0]);
B[0]=unique (B+1,b+1+b[0])-(b+1);
Sort (Q+1,Q+1+M,MY_CMP1);
for (int i=1;i<=n;i++) Id_c[i]=find (C[i]);
Q[0].x=q[0].y=1;
for (int i=1;i<=m;i++) {work (q[i-1].x,q[i].x);
Work (Q[I-1].Y,Q[I].Y);
int _lca=lca (Q[I].X,Q[I].Y); Rev (_LCA); Q[i].res=ans;
Rev (_LCA);
Sort (Q+1,Q+1+M,MY_CMP2);
for (int i=1;i<=m;i++) printf ("%d\n", q[i].res);
return 0; }