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.
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.
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
#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] );
}
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] );
}
相关文章推荐
- 【SPOJ COT2】Count on a tree II,树上莫队
- SPOJ - COT2 : Count on a tree II (树上莫队)
- SPOJ-COT2 Count on a tree II(树上莫队)
- [spoj COT2- Count on a tree II] 树上莫队
- SPOJ COT2 Count on a tree II(路径树上莫队)
- SPOJ COT2 Count on a tree II 树上莫队
- spoj_cot2 Count on a tree II(树上莫队+离散化)
- [SPOJ COT2]-Count on a tree II-树上莫队
- SPOJ Count on a tree II(树上莫队)
- 【SPOJ10707】Count on a tree II-树上莫队算法
- SPOJ 10707 Count on a Tree II 树上莫队
- spoj_cot2 Count on a tree II(树上莫队+离散化)
- 【SPOJ】Count On A Tree II(树上莫队)
- [树上莫队] SPOJ COT2 Count on a tree II
- 【spoj】【COT2 - Count on a tree II】【莫队算法】
- BZOJ 2589 Spoj 10707 Count on a tree II 强制在线莫队算法(TLE)
- SPOJcot2 Count on a tree II (树上莫队)
- SPOJ.COT2 Count on a tree II(树上莫队)
- SPOJ COT2 Count on a tree II [树上莫队]
- SPOJ COT2 Count on a tree II(树上莫队)