首页 > 代码库 > spoj COT2 - Count on a tree II

spoj COT2 - Count on a tree II

COT2 - Count on a tree II

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

#tree

 

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 2105 2 9 3 8 5 7 71 21 31 43 53 63 74 82 57 8
Output:44
 Submit solution!
 

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

 

树上莫队

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

dfs分块。。

#include<cmath>#include<cstdio>#include<algorithm>using namespace std;#define N 40001#define M 100001int 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\n",ans[i]);}

 

 

spoj COT2 - Count on a tree II