您的位置:首页 > 其它

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

2017-01-26 16:30 375 查看
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 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 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 (uv).
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
题意:给一棵染过色的数,每个点有一个颜色,每次询问树上一段路径的颜色数量。

分析: 树上莫队,通过dfs序可以把树上的一段路径转换为一段序列,剩下做法就和一般的序列莫队一样了。

#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#define N 40015
using namespace std;
int n,m,ans,u,v,Time,block,Ans[100005],a
,vis
,s
,rd
,cd
,deep
,fh[2*N],color
,f
[31];
vector<int> G
;
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<<j) <= n;j++)
for(int i = 1;i <= n;i++)
f[i][j] = f[f[i][j-1]][j-1];
}
int LCA(int u,int v)
{
if(deep[u] < deep[v]) swap(u,v);
int d = deep[u] - deep[v];
for(int i = 0;i < 30;i++)
if((1<<i) & d) u = f[u][i];
if(u == v) return u;
for(int i = 29;i >= 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]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: