(以下路径都不包含 LCA LCA )
考虑当前知道路径 (u,v) ( u , v ) 的信息,想要知道 (t,v) ( t , v ) 的信息,只需把 (u,t) ( u , t ) 上的点状态取反即可,那么复杂度是和 (u,t) ( u , t ) 的长度相关的。
于是我们考虑把树分块,每当一个点的子树大小 ≥n−−√ ≥ n 就拎出来成为一块。 idi i d i 表示 i i 号点所在块的编号,那么我们按 (idi,dfni) ( i d i , d f n i ) 给询问排序,不难证明复杂度是 O(nn−−√) O ( n n )
模板题:SPOJ COT2
代码:
#include
#include
#include
#include
#define N 40010
#define M 100010
#define pii pair
#define MP make_pair
#define fs first
#define sc second
using namespace std;
const int B=200;
int n,m,nc,nb,tote,to[N<<1],con[N<<1],nxt[N<<1],col[N],z[N],sz[N],blk[N],dfn[N],fa[N],ver[N<<1],tim,sta[N],top,lg[N<<1],cnt[N],ans;
bool vis[N];
pii st[20][N<<1];
int read()
{
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') f=-1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x*f;
}
struct node
{
int x,y,id,ans;
}q[M];
bool cmp(node a,node b)
{
if(blk[a.x]==blk[b.x]) return dfn[a.y]y];
return blk[a.x]x];
}
bool cmpid(node a,node b)
{
return a.idint x,int y)
{
to[++tote]=y;
nxt[tote]=con[x];
con[x]=tote;
}
void dfs(int v)
{
dfn[v]=++tim;ver[tim]=v;
sz[v]=1;sta[++top]=v;
for(int p=con[v];p;p=nxt[p])
if(to[p]!=fa[v]) fa[to[p]]=v,dfs(to[p]),ver[++tim]=v,sz[v]+=sz[to[p]];
if(sz[v]>=B)
for(sz[v]=0,nb++;sta[top+1]!=v;top--)
blk[sta[top]]=nb;
}
void init()
{
lg[1]=0;
for(int i=1;i<(n<<1);i++) st[0][i]=MP(dfn[ver[i]],ver[i]);
for(int i=2;i<(n<<1);i++) lg[i]=lg[i>>1]+1;
for(int k=1;(1<1);k++)
for(int i=1;i+(1<1<(n<<1);i++)
st[k][i]=min(st[k-1][i],st[k-1][i+(1<<(k-1))]);
}
int LCA(int x,int y)
{
int dx=dfn[x],dy=dfn[y];
if(dx>dy) swap(dx,dy);
int k=lg[dy-dx+1];
return min(st[k][dx],st[k][dy-(1<1]).sc;
}
void update(int x,int y)
{
int lca=LCA(x,y);
for(;x!=lca;x=fa[x])
if(vis[x]) vis[x]=0,cnt[col[x]]--,ans-=(cnt[col[x]]==0);
else vis[x]=1,ans+=(cnt[col[x]]==0),cnt[col[x]]++;
for(;y!=lca;y=fa[y])
if(vis[y]) vis[y]=0,cnt[col[y]]--,ans-=(cnt[col[y]]==0);
else vis[y]=1,ans+=(cnt[col[y]]==0),cnt[col[y]]++;
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++)
col[i]=z[i]=read();
sort(z+1,z+n+1);
for(int i=1;i<=n;i++)
col[i]=lower_bound(z+1,z+n+1,col[i])-z;
for(int i=1;iint x=read(),y=read();
ins(x,y);ins(y,x);
}
dfs(1);
init();
for(int i=1;i<=m;i++)
{
int x=read(),y=read();
q[i]=(node){x,y,i,0};
}
sort(q+1,q+m+1,cmp);
int curx=1,cury=1;ans=0;
for(int i=1;i<=m;i++)
{
update(curx,q[i].x);curx=q[i].x;
update(cury,q[i].y);cury=q[i].y;
q[i].ans=ans+(cnt[col[LCA(q[i].x,q[i].y)]]==0);
}
sort(q+1,q+m+1,cmpid);
for(int i=1;i<=m;i++)
printf("%d\n",q[i].ans);
return 0;
}