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:
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.
For each operation, print its result.
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
题意:给一棵染过色的数,每个点有一个颜色,每次询问树上一段路径的颜色数量。
分析: 树上莫队,通过dfs序可以把树上的一段路径转换为一段序列,剩下做法就和一般的序列莫队一样了。
#include
#include
#include
#include
#include
#define N 40015
using namespace std;
int n,m,ans,u,v,Time,block,Ans[100005],a[N],vis[N],s[N],rd[N],cd[N],deep[N],fh[2*N],color[N],f[N][31];
vector G[N];
struct thing
{
int l,r,bl,lca,num;
friend bool operator < (thing a,thing b)
{
if(a.bl == b.bl) return a.r < b.r;
return a.bl < b.bl;
}
}ask[100005];
void dfs(int u,int fa)
{
deep[u] = deep[fa] + 1;
f[u][0] = fa;
rd[u] = ++Time;
fh[Time] = u;
for(int i = 0;i < G[u].size();i++)
{
int v = G[u][i];
if(v != fa) dfs(v,u);
}
cd[u] = ++Time;
fh[Time] = u;
}
void init()
{
for(int j = 1;(1<= 0;i--)
{
if(f[u][i] != f[v][i])
{
u = f[u][i];
v = f[v][i];
}
}
u = f[u][0];
return u;
}
void updata(int u)
{
if(vis[u])
{
if(!color[a[u]]) ans++;
color[a[u]]++;
}
else
if(!(--color[a[u]])) ans--;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++)
{
scanf("%d",&a[i]);
s[i] = a[i];
}
sort(s+1,s+1+n);
for(int i = 1;i <= n;i++) a[i] = lower_bound(s+1,s+1+n,a[i]) - s;
for(int i = 1;i < n;i++)
{
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(n/2+1,0);
init();
block = (int)(2.82*n/sqrt(m)) + 1;
for(int i = 1;i <= m;i++)
{
scanf("%d%d",&u,&v);
ask[i].lca = LCA(u,v);
ask[i].num = i;
if(ask[i].lca == u || ask[i].lca == v)
{
ask[i].lca = -1;
if(deep[u] > deep[v]) swap(u,v);
ask[i].l = rd[u],ask[i].r = rd[v];
}
else
{
if(cd[u] > rd[v]) swap(u,v);
ask[i].l = cd[u],ask[i].r = rd[v];
}
ask[i].bl = (ask[i].l-1)/block + 1;
}
sort(ask+1,ask+1+m);
int l = 1,r = 1;
color[a[fh[1]]] = 1;
vis[fh[1]] = 1;
ans = 1;
for(int i = 1;i <= m;i++)
{
for(;r > ask[i].r;r--)
{
vis[fh[r]] ^= 1;
updata(fh[r]);
}
for(r++;r <= ask[i].r;r++)
{
vis[fh[r]] ^= 1;
updata(fh[r]);
}
for(;l < ask[i].l;l++)
{
vis[fh[l]] ^= 1;
updata(fh[l]);
}
for(l--;l >= ask[i].l;l--)
{
vis[fh[l]] ^= 1;
updata(fh[l]);
}
if(ask[i].lca != -1)
if(!color[a[ask[i].lca]]) Ans[ask[i].num] = 1;
Ans[ask[i].num] += ans;
l = ask[i].l,r = ask[i].r;
}
for(int i = 1;i <= m;i++) printf("%d\n",Ans[i]);
}