题目链接

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. asp.net文件下载

    protected void btn_Down(object sender, EventArgs e) { string filePath = Server.MapPath("/TradeL ...

  2. Android学习之DialogFragment

    DialogFrament是Android sdk中的对话框基类,开发人员可以针对此类进行扩展.他可以扩展出Android中的多种对话框,比如alertdialog,listdialog,radiod ...

  3. 06JS高级创建对象使用原型共享对象方法

    <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...

  4. @property属性

    1. 读写属性(readwrite/ readonly) 默认为readwrite,表示该属性既可以读取,也可以给该属性变量赋值:readonly则表示只能读取该属性变量. 2. 原子属性 (atom ...

  5. 初学DIV+CSS要记住的

    初学DIV+CSS?有六个问题需要您关注一下!作为DIV+CSS初学者,如果在动手写代码之前对网页整体结构由一个清晰认识的话,写起来会事半功倍!但是,写的过程中总是有这样那样的问题,使得我们不得不停下 ...

  6. dede 设置为全动态浏览

    将织梦所有栏目设置为“使用动态页”,可以再建立栏目时选择“使用动态页”:也可以执行下面的SQL语句.update dede_arctype set isdefault=-1 将网站所有文档都设置为“仅 ...

  7. Eclipse开启Mybatis-config.xml配置文件智能提示

    使用Java开发的程序员一般在学习的时候,可能都会涉及到使用配置文件,在使用Eclipse类似IDE进行编辑配置配置文件的时候,如果配置文件不能自动联想,是一件比较恼人的事情.笔者这里拿mybatis ...

  8. excel文件后台代码

    很多情况下,我们都需要从Excel中获取数据来创建Word报表文档.首先在Excel中分析数据,然后将分析结果导出到Word文档中发布.技术实现方式:1.创建Word模板,用来作为数据分析结果发布平台 ...

  9. Asp.net MVC1 学习1

    此次博客的编写纯属是为了记录自己的学习情况 asp.net mvc学习教程来自于重点,地址:http://v.youku.com/v_show/id_XNDQ4MDQ1MzI=.html?f=2416 ...

  10. arrowTip 提示

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...