spoj COT2

COT2 - Count on a tree II

http://www.spoj.com/problems/COT2/

You are given a tree with N nodes. The tree nodes are numbered from 1 to N. Each node has an integer weight.

We will ask you to perform the following operation:

  • u v : ask for how many different integers that represent the weight of nodes there are on the path from u tov.

Input

In the first line there are two integers N and M. (N <= 40000, M <= 100000)

In the second line there are N integers. The i-th integer denotes the weight of the i-th node.

In the next N-1 lines, each line contains two integers u v, which describes an edge (u, v).

In the next M lines, each line contains two integers u v, which means an operation asking for how many different integers that represent the weight of nodes there are on the path from u to v.

Output

For each operation, print its result.

Example

Input:
8 2
105 2 9 3 8 5 7 7
1 2
1 3
1 4
3 5
3 6
3 7
4 8
2 5
7 8
Output:
4
4
 

题意:问树上两点间有多少不同的权值 

树上莫队

开始狂T,发现自己竟是按节点编号划分的块!!

dfs分块。。

#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
#define N 40001
#define M 100001
int n,m,siz,tmp;
int hash[N],key[N];
int front[N],to[N*2],nxt[N*2],tot;
int fa[N],deep[N],id[N],son[N],bl[N],block[N];
bool vis[N];
int sum[N],ans[M];
struct node
{
    int l,r,id;
    bool operator < (node p) const
    {
        if(block[l]!=block[p.l]) return block[l]<block[p.l];
        return block[r]<block[p.r];
    }
}e[M];
int read(int &x)
{
    x=0; char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); }
}
void add(int x,int y)
{
    to[++tot]=y; nxt[tot]=front[x]; front[x]=tot;
    to[++tot]=x; nxt[tot]=front[y]; front[y]=tot;
}
void dfs(int x)
{
    son[x]++;
    for(int i=front[x];i;i=nxt[i])
    {
        if(to[i]==fa[x]) continue;
        deep[to[i]]=deep[x]+1;
        fa[to[i]]=x;
        dfs(to[i]);
        son[x]+=son[to[i]];
    }
}
void dfs2(int x,int top)
{
    id[x]=++tot;
    bl[x]=top;
    block[x]=(tot-1)/siz+1;
    int y=0;
    for(int i=front[x];i;i=nxt[i])
    {
        if(to[i]==fa[x]) continue;
        if(son[to[i]]>son[y]) y=to[i];
    }
    if(!y) return;
    dfs2(y,top);
    for(int i=front[x];i;i=nxt[i])
    {
        if(to[i]==fa[x]||to[i]==y) continue;
        dfs2(to[i],to[i]);
    }
}
void point(int u)
{
    if(vis[u]) tmp-=(!--sum[hash[u]]);
    else tmp+=(++sum[hash[u]]==1);
    vis[u]^=1;
}
void path(int u,int v)
{
    while(u!=v)
    {
        if(deep[u]>deep[v]) point(u),u=fa[u];
        else point(v),v=fa[v];
    }
}
int get_lca(int u,int v)
{
    while(bl[u]!=bl[v])
    {
        if(deep[bl[u]]<deep[bl[v]]) swap(u,v);
        u=fa[bl[u]];
    }
    return deep[u]<deep[v] ? u : v;
}
int main()
{
    read(n);read(m);  siz=sqrt(n);
    for(int i=1;i<=n;i++) read(key[i]),hash[i]=key[i];
    sort(key+1,key+n+1);
    key[0]=unique(key+1,key+n+1)-(key+1);
    for(int i=1;i<=n;i++) hash[i]=lower_bound(key+1,key+key[0]+1,hash[i])-key;
    int x,y;
    for(int i=1;i<n;i++)
    {
        read(x); read(y);
        add(x,y);
    }
    tot=0;
    dfs(1);
    dfs2(1,1);
    for(int i=1;i<=m;i++)
    {
        read(e[i].l); read(e[i].r);
        e[i].id=i;
    }
    sort(e+1,e+m+1);
    int L=1,R=1,lca;
    for(int i=1;i<=m;i++)
    {
        if(id[e[i].l]>id[e[i].r]) swap(e[i].l,e[i].r);
        path(L,e[i].l);
        path(R,e[i].r);
        lca=get_lca(e[i].l,e[i].r);
        point(lca);
        ans[e[i].id]=tmp;
        point(lca);
        L=e[i].l; R=e[i].r;
    }
    for(int i=1;i<=m;i++) printf("%d
",ans[i]);
}
 
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7071492.html