题意:
询问路径上多少种不同的点权
我一直写了假的莫队!!!!
正确的排序方式是$(pos[u],dfn[v])$,我却一直用原始点的编号排序!!!
然后你会发现代码中有一些卡常...
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> using namespace std; typedef long long ll; const int N=2e5+5; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int n,Q,a[N],mp[N],u,v; struct edge{int v,ne;} e[N<<1]; int cnt,h[N]; inline void ins(int u,int v){ e[++cnt]=(edge){v,h[u]}; h[u]=cnt; e[++cnt]=(edge){u,h[v]}; h[v]=cnt; } int block, pos[N], m, st[N], top; int fa[N][18], deep[N], dfn[N], dfc; void dfs(int u){ dfn[u]=++dfc; for(int i=1; (1<<i)<=deep[u]; i++) fa[u][i]=fa[ fa[u][i-1] ][i-1]; int bot=top; for(int i=h[u];i;i=e[i].ne) if(e[i].v!=fa[u][0]){ fa[e[i].v][0]=u; deep[e[i].v]=deep[u]+1; dfs(e[i].v); if(top-bot>=block){ m++; while(top!=bot) pos[st[top--]]=m; } } st[++top]=u; } inline int lca(int x,int y){ if(deep[x]<deep[y]) swap(x, y); int bin=deep[x]-deep[y]; for(int i=0;i<17;i++) if((1<<i)&bin) x=fa[x][i]; if(x==y) return x; for(int i=16;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i], y=fa[y][i]; return x==y ? x : fa[x][0]; } struct meow{ int u, v, id; bool operator <(const meow &a) const {return pos[u]==pos[a.u] ? dfn[v]<dfn[a.v] : pos[u]<pos[a.u];} }q[N]; int vis[N], cou[N], now, ans[N]; inline void Xor(int u){ if(!vis[u]) now+= (++cou[a[u]])==1; else now-= (--cou[a[u]])==0; vis[u]^=1; } inline void move(int x,int y){ //printf("%d --> %d %d ",x,y,now); if(deep[x]<deep[y]) swap(x, y); while(deep[x]>deep[y]) Xor(x), x=fa[x][0]; while(x!=y) Xor(x), Xor(y), x=fa[x][0], y=fa[y][0]; } void modui(){ u=1, v=1; for(int i=1;i<=Q;i++){ if(u!=q[i].u) move(u, q[i].u), u=q[i].u; if(v!=q[i].v) move(v, q[i].v), v=q[i].v; int anc=lca(u, v); ans[q[i].id]= now + (cou[a[anc]]==0); } } int main(){ freopen("in","r",stdin); n=read(); Q=read(); for(int i=1;i<=n;i++) a[i]=mp[i]=read(); sort(mp+1, mp+1+n); mp[0]=unique(mp+1, mp+1+n)-mp-1; for(int i=1;i<=n;i++) a[i]=lower_bound(mp+1, mp+1+mp[0], a[i])-mp; for(int i=1;i<n ;i++) ins(read(), read() ); block= sqrt(n); dfs(1); while(top) pos[st[top--]]=m; for(int i=1;i<=Q;i++){ u=read(), v=read(); if(pos[u]>pos[v]) swap(u, v); q[i]=(meow){u, v, i}; } sort(q+1, q+1+Q); modui(); for(int i=1;i<=Q;i++) printf("%d ",ans[i]); }