题目链接

http://codeforces.com/blog/entry/43230树上莫队从这里学的,  受益匪浅..

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <queue>
#include <stack>
#include <bitset>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, n, a) for(int i = a; i<n; i++)
#define fi first
#define se second
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-;
const int mod = 1e9+;
const int inf = ;
const int dir[][] = { {-, }, {, }, {, -}, {, } };
const int maxn = 4e4+;
int in[maxn], head[maxn], num, out[maxn], cnt, val[maxn], ans[], a[maxn];
int f[maxn], d[maxn], p[maxn][], n, m, vis[maxn], times[maxn], res, id[maxn*];
struct node
{
int to, nextt;
}e[maxn*];
struct query
{
int l, r, lca, id, block;
bool operator < (query a) const
{
if(block == a.block)
return r<a.r;
return block<a.block;
}
}q[];
void add(int u, int v) {
e[num].to = v, e[num].nextt = head[u], head[u] = num++;
}
void init() {
mem1(head);
mem1(p);
}
void dfs(int u, int fa) {
in[u] = ++cnt;
id[cnt] = u;
f[u] = fa;
for(int i = head[u]; ~i; i = e[i].nextt) {
int v = e[i].to;
if(v == fa)
continue;
d[v] = d[u]+;
dfs(v, u);
}
out[u] = ++cnt;
id[cnt] = u;
}
void initLca() {
int i, j;
for(i = ; i<=n; i++) {
p[i][] = f[i];
}
for(j = ; (<<j)<=n; j++) {
for(i = ; i<=n; i++) {
if(~p[i][j-])
p[i][j] = p[p[i][j-]][j-];
}
}
}
int lca(int u, int v) {
if(d[u]<d[v])
swap(u, v);
int i, j;
for(i = ; (<<i)<=d[u]; i++)
;
i--;
for(j = i; j>=; j--)
if(d[u]-(<<j)>=d[v])
u = p[u][j];
if(u == v)
return v;
for(j = i; j>=; j--) {
if(p[u][j] != - && p[u][j] != p[v][j]) {
u = p[u][j];
v = p[v][j];
}
}
return f[u];
}
void check(int x) {
if(vis[x] && --times[val[x]]==) {
res--;
} else if(vis[x]== && times[val[x]]++ == ) {
res++;
}
vis[x]^=;
}
void cal() {
int L = q[].l, R = q[].l-;
for(int i = ; i<m; i++) {
while(L<q[i].l) {
check(id[L++]);
}
while(L>q[i].l) {
check(id[--L]);
}
while(R<q[i].r) {
check(id[++R]);
}
while(R>q[i].r) {
check(id[R--]);
}
if(q[i].lca != id[q[i].l] && q[i].lca != id[q[i].r]) {
check(q[i].lca);
}
ans[q[i].id] = res;
if(q[i].lca != id[q[i].l] && q[i].lca != id[q[i].r]) {
check(q[i].lca);
}
}
}
int main()
{
int u, v;
cin>>n>>m;
int BLOCK = sqrt(n);
init();
for(int i = ; i<=n; i++) {
scanf("%d", &val[i]);
a[i-] = val[i];
}
sort(a, a+n);
int N = unique(a, a+n)-a;
for(int i = ; i<=n; i++) {
val[i] = lower_bound(a, a+N, val[i])-a+;
}
for(int i = ; i<n-; i++) {
scanf("%d%d", &u, &v);
add(u, v);
add(v, u);
}
d[] = ;
dfs(, -);
initLca();
for(int i = ; i<m; i++) {
scanf("%d%d", &u, &v);
if(in[u]>in[v])
swap(u, v);
q[i].lca = lca(u, v);
if(q[i].lca == u) {
q[i].l = in[u];
q[i].r = in[v];
} else {
q[i].l = out[u];
q[i].r = in[v];
}
q[i].block = q[i].l/BLOCK;
q[i].id = i;
}
sort(q, q+m);
cal();
for(int i = ; i<m; i++) {
printf("%d\n", ans[i]);
}
return ;
}

spoj COT2 - Count on a tree II 树上莫队的更多相关文章

  1. SPOJ COT2 Count on a tree II 树上莫队算法

    题意: 给出一棵\(n(n \leq 4 \times 10^4)\)个节点的树,每个节点上有个权值,和\(m(m \leq 10^5)\)个询问. 每次询问路径\(u \to v\)上有多少个权值不 ...

  2. SP10707 COT2 - Count on a tree II (树上莫队)

    大概学了下树上莫队, 其实就是在欧拉序上跑莫队, 特判lca即可. #include <iostream> #include <algorithm> #include < ...

  3. SP10707 COT2 - Count on a tree II [树上莫队学习笔记]

    树上莫队就是把莫队搬到树上-利用欧拉序乱搞.. 子树自然是普通莫队轻松解决了 链上的话 只能用树上莫队了吧.. 考虑多种情况 [X=LCA(X,Y)] [Y=LCA(X,Y)] else void d ...

  4. [SPOJ]Count on a tree II(树上莫队)

    树上莫队模板题. 使用欧拉序将树上路径转化为普通区间. 之后莫队维护即可.不要忘记特判LCA #include<iostream> #include<cstdio> #incl ...

  5. SPOJ COT2 - Count on a tree II(LCA+离散化+树上莫队)

    COT2 - Count on a tree II #tree You are given a tree with N nodes. The tree nodes are numbered from  ...

  6. 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 ...

  7. SPOJ COT2 Count on a tree II (树上莫队,倍增算法求LCA)

    题意:给一个树图,每个点的点权(比如颜色编号),m个询问,每个询问是一个区间[a,b],图中两点之间唯一路径上有多少个不同点权(即多少种颜色).n<40000,m<100000. 思路:无 ...

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

    题目链接:http://www.spoj.com/problems/COT2/ You are given a tree with N nodes.The tree nodes are numbere ...

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

    题目链接:http://www.spoj.com/problems/COT2/ 参考博客:http://www.cnblogs.com/xcw0754/p/4763804.html上面这个人推导部分写 ...

随机推荐

  1. CSS样式做圆角

    我处理圆角的版本是由内置的绝对定位的四个div组成,每个div都有唯一的圆角图片作CSS Sprite操作.我们将会这样做:  是什么方式导致这项技术表现得这么了不起呢(What makes this ...

  2. Free Sql Server SMSS format Plugin

    免费Sql Server 格式化插件 http://www.apexsql.com/sql_tools_refactor.aspx http://architectshack.com/PoorMans ...

  3. WPF那些事儿

    概述 感觉学习的东西必须做个记录,不然很快就忘掉了.现在把WPF学习过程中一些零碎的东西记录在下面,没有具体的主题,想到啥.看到啥都写在这里,算是复习一下并做个备忘吧. 1. 等待对话框 看到同事做的 ...

  4. Android周笔记(9.8-14)(持续更新)

    本笔记记录一周内的小知识点和一些心学习的Demo. 1.PopupWindow: new 一个activity_pop_window:id为popwindow的Button,id为hello123的T ...

  5. 在Google map图上做标记,并把标记相连接

    <!DOCTYPE html> <html> <head> <title>GeoLocation</title> <meta name ...

  6. mysql性能优化学习笔记(5)数据库结构优化

    一.选择合适的数据类型    1.使用可存下数据的最小的数据类型    2.使用简单地数据类型,Int<varchar    3.尽可能使用not null定义字段    4.尽量少用text, ...

  7. SQL Server 加密层级

    ---------------------------------------------------------------------------------------------------- ...

  8. EEPROM和flash的区别

    存储器分为两大类:ram和rom.ram就不讲了,今天主要讨论rom. rom最初不能编程,出厂什么内容就永远什么内容,不灵活.后来出现了prom,可以自己写入一次,要是写错了,只能换一片,自认倒霉. ...

  9. RBF network

    1.radial basis function RBF表示某种距离,$\mu_m$为中心点,相当于将点$x$到中心点的某种距离作为特征转换 Output方法可以根据需求任意选取(比如使用SVM,log ...

  10. matlab 矩阵

    假设矩阵A=[1 3;4 2] 1.对角置零: A-diag(diag(A)) 2.求A的特征值以及特征向量: 用到eig(A)函数,此函数有五种用法,如下: 2.1 E=eig(A):求矩阵A的全部 ...