您的位置:首页 > 其它

SPOJ--Count on a tree II(树上莫队)

2014-10-14 00:50 411 查看
Description

 

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 perfrom the following operation:

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

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 ith integer denotes the weight of the ith 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 5 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 


 #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <queue>
#include <string>
#include <set>
#include <stack>
using namespace std;
#define LL long long int
#define maxn 100800
#define maxm 210008
int vv[maxm],nxt[maxm],first[maxn],e,deep;
void init()
{
memset(first,-1,sizeof(first));
e = deep = 0;
}
void addedge(int u,int v)
{
vv[e] = v; nxt[e] = first[u]; first[u] = e++;
vv[e] = u; nxt[e] = first[v]; first[v] = e++;
}
int val[maxn],in[maxn],out[maxn];
int col[maxn],a[maxn],dep[maxn];
int lisan[maxm],cnt;
int fa[maxn][20];
int ID(int x)
{
return lower_bound(lisan,lisan+cnt,x) - lisan;
}

void dfs(int u,int pre)
{
in[u] = ++deep; a[deep] = val[u];
col[deep] = 1; dep[u] = dep[pre] + 1;
for(int i = 0;fa[u][i];i++)
fa[u][i+1] = fa[fa[u][i]][i];
for(int i = first[u];i != -1;i = nxt[i])
{
int v = vv[i];
if(v != pre)
fa[v][0] = u,dfs(v,u);
}
out[u] = ++deep; a[deep] = val[u];
col[deep] = -1;
}
int jump(int u,int d)
{
for(int i = 0;d;i++) if(d >> i & 1)
u = fa[u][i],d -= 1 << i;
return u;
}
int lca(int u,int v)
{
if(dep[u] < dep[v]) swap(u,v);
u = jump(u,dep[u] - dep[v]);
for(int i = 19;i >= 0;i--)
if(fa[u][i] != fa[v][i])
u = fa[u][i],v = fa[v][i];
return u == v ? u:fa[u][0];
}

int B;
struct Q
{
int u,v;
int b,id;
void scan(int i)
{
id = i;
scanf("%d%d",&u,&v);
if(in[u] > in[v]) swap(u,v);
b = in[u] / B;
}
bool operator < (const Q & a) const
{
return b < a.b || a.b == b && in[v] < in[a.v];
}
}q[maxm];
int F,U,V;
int ans,num[maxn];
int sum[maxn];
void gao(int x,int k)
{
int pre = num[x];
num[x] += k;
if(pre == 0 && num[x] == 1) ++ans;
if(pre == 1 && num[x] == 0) --ans;
}
int solve( int f, int u, int v )
{
while( F < f ){
++F;
gao( a[F], -col[F] );
gao( a[F], -col[F] );
}
while( F > f ){
gao( a[F], col[F] );
gao( a[F], col[F] );
--F;
}
gao( a[f], col[f] );

while( U < u ){
++U;
gao( a[U], col[U] );
}
while( U > u ){
gao( a[U], -col[U] );
--U;
}
while( V < v ){
++V;
gao( a[V], col[V] );
}
while( V > v ){
gao( a[V], -col[V] );
--V;
}
int tmp = ans;
gao( a[f], -col[f] );
return tmp;
}
int main()
{
int n,m,u,v;
scanf("%d%d",&n,&m);
cnt = 0;
init();
for(int i = 1;i <= n;i++)
{
scanf("%d",&val[i]);
lisan[cnt++] = val[i];
}
sort(lisan,lisan+cnt);
cnt = unique(lisan,lisan+cnt) - lisan;
for(int i = 1;i <= n;i++) val[i] = ID(val[i]);
memset(first,-1,sizeof(first));
e = 0;
for(int i = 1;i < n;i++)
{
scanf("%d%d",&u,&v);
addedge(u,v);
}
B = sqrt(n+0.5);
memset(fa,0,sizeof(fa));
dfs(1,0);
for(int i = 0;i < m;i++)
q[i].scan(i);
sort(q,q+m);
memset( num, 0, sizeof(num) );
F = U = V = ans = 0;
int f;
for( int i = 0; i < m; ++i ){
u = q[i].u, v = q[i].v;
f = lca( u, v );
sum[q[i].id] = solve( in[f], in[u], in[v] );
}
for( int i = 0; i < m; ++i )
printf( "%d\n", sum[i] );
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: