题目链接

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. 南阳师范学院ACM集训队博客使用方法

    南阳师范学院ACM集训队博客使用方法 为方便大家交流,我们使用的是同一个用户名和密码,所以请不要随意修改用户名和密码,不然大家都登不上了,谢谢! 首先进入主页:http://www.cnblogs.c ...

  2. python学习笔记:python序列

    python序列包括字符串.列表和元组三部分,下面先总的说一下python序列共有的一些操作符和内建函数. 一.python序列 序列类型操作符 标准类型的操作符一般都能适用于所有的序列类型,这里说一 ...

  3. oracle体系结构

    oracle体系结构有四个部分组成分别为:oracle 服务器.用户进程.服务器进程.其他关键文件.其中oracle服务器又有实例(instance)和database组成是一个数据库管理系统. 一. ...

  4. vs2012 发布网站丢失文件

    问题描述 在发布网站时,发现上线的网站总是功能缺失,而本地代码确实没问题. 到发布网站的磁盘去查看,发现丢失了很多静态页面文件. 这是一个很奇怪的问题:mvc的网站,丢失了很多View(大部分的csh ...

  5. hdu 5446 Unknown Treasure 中国剩余定理+lucas

    题目链接 求C(n, m)%p的值, n, m<=1e18, p = p1*p2*...pk. pi是质数. 先求出C(n, m)%pi的值, 然后这就是一个同余的式子. 用中国剩余定理求解. ...

  6. Swift笔记01

    变量使用var 来声明,常量是所有let ,变量名没什么限制 中文表情都可以 ,一般还是使用英文. var str = "luoshuai "  //swift语句后面不需要; l ...

  7. Oracle EBS-SQL (PO-9):检查期间采购订单执行情况.sql

    --采购订单执行情况查询(七天内接收情况)select pha.segment1       采购订单,         msib.segment1      物料编码,         pla.qu ...

  8. 解决:“Ubuntu 10.04 LTS _Lucid Lynx_ - Release i38...

    编译android源码,找不到g++.通过apt-get下载时候,总是提示“Ubuntu 10.04 LTS _Lucid Lynx_ - Release i386 (20100429)” 的盘片插入 ...

  9. 论山寨手机与Android 【15】结束语

    去年11月,与人讨论山寨版Android智能手机的前景,最初觉得这个问题很容易回答.但是三言两语之后,不仅听者茫然,而且言者自己也意识到条理紊乱,说服力不强.于是决定写几篇文章,把这个问题展开说说.所 ...

  10. memcache 安装教程

    memcached:官网http://memcached.org/ 说明:memcached本身没有Linux版本,网上的windows 版本都是个人开发的. memcached和memcache区别 ...