spoj COT2(树上莫队)

模板。树上莫队的分块就是按dfn分,然后区间之间转移时注意一下就好。有个图方便理解http://blog.csdn.net/thy_asdf/article/details/47377709;

#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=50010;
int ccc[maxn],col[maxn],n,m,last[maxn],pre[maxn*2],other[maxn*2],d[maxn],bel[maxn],f[maxn][25];
int res,bo,ind,dfn[maxn],ans[maxn*2],t,cnt,sta[maxn],top,vis[maxn],tong[maxn],ttt[maxn];
struct que{
    int u,v,id;
    bool operator<(const que&tmp)const{
        if(bel[u]==bel[tmp.u])return dfn[v]<dfn[tmp.v];
        return bel[u]<bel[tmp.u];
    }
}q[maxn*2];
void add(int x,int y){++t;pre[t]=last[x];last[x]=t;other[t]=y;}
int dfs(int x){
    int siz=0;
    dfn[x]=++ind;
    for(int i=last[x];i;i=pre[i]){
        int v=other[i];
        if(v==f[x][0])continue;
        d[v]=d[x]+1;f[v][0]=x;
        siz+=dfs(v);
        if(siz>=bo){
            ++cnt;
            for(int j=1;j<=siz;++j)
            bel[sta[top--]]=cnt;
            siz=0;
        }
    }
    sta[++top]=x;
    return siz+1;
}
void change(int x){
    if(!vis[x]){vis[x]=1;tong[col[x]]++;if(tong[col[x]]==1)res++;}
    else{vis[x]=0;tong[col[x]]--;if(tong[col[x]]==0)res--;}
}
void solve(int u,int v){
    while(u!=v){
        if(d[u]>d[v])change(u),u=f[u][0];
        else change(v),v=f[v][0];
    }
}
int lca(int x,int y){
    if(d[x]<d[y])swap(x,y);
    for(int i=20;i>=0;--i)
    if(d[f[x][i]]>=d[y])x=f[x][i];
    if(x==y)return x;
    for(int i=20;i>=0;--i)
    if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    return f[x][0];
}
int main(){
    cin>>n>>m;
    int x,y;bo=sqrt(n+0.5);
    for(int i=1;i<=n;++i){
        scanf("%d",&ccc[i]);
        ttt[i]=ccc[i];
    }
    sort(ttt+1,ttt+n+1);
    int len=unique(ttt+1,ttt+n+1)-ttt-1;
    for(int i=1;i<=n;++i){
        col[i]=lower_bound(ttt+1,ttt+len+1,ccc[i])-ttt;
    }
    for(int i=1;i<n;++i){
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    d[1]=1;dfs(1);
    ++cnt;
    while(top)bel[sta[top--]]=cnt;
    for(int j=1;j<=20;++j)
      for(int i=1;i<=n;++i)
        f[i][j]=f[f[i][j-1]][j-1];
    for(int i=1;i<=m;++i){
        q[i].id=i;
        scanf("%d%d",&q[i].u,&q[i].v);
        if(dfn[q[i].u]>dfn[q[i].v])swap(q[i].u,q[i].v);
    }
    sort(q+1,q+m+1);
    int op=lca(q[1].u,q[1].v);
    solve(q[1].u,q[1].v);
    change(op);ans[q[1].id]=res;change(op);
    for(int i=2;i<=m;++i){
        solve(q[i-1].u,q[i].u);solve(q[i-1].v,q[i].v);
        op=lca(q[i].u,q[i].v);
        change(op);ans[q[i].id]=res;change(op);
    }
    for(int i=1;i<=m;++i){
        printf("%d
",ans[i]);
    }
    //system("pause");
    return 0;
}
原文地址:https://www.cnblogs.com/dibaotianxing/p/8353227.html