spoj COT2 - Count on a tree II 树上莫队
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 树上莫队的更多相关文章
- SPOJ COT2 Count on a tree II 树上莫队算法
题意: 给出一棵\(n(n \leq 4 \times 10^4)\)个节点的树,每个节点上有个权值,和\(m(m \leq 10^5)\)个询问. 每次询问路径\(u \to v\)上有多少个权值不 ...
- SP10707 COT2 - Count on a tree II (树上莫队)
大概学了下树上莫队, 其实就是在欧拉序上跑莫队, 特判lca即可. #include <iostream> #include <algorithm> #include < ...
- SP10707 COT2 - Count on a tree II [树上莫队学习笔记]
树上莫队就是把莫队搬到树上-利用欧拉序乱搞.. 子树自然是普通莫队轻松解决了 链上的话 只能用树上莫队了吧.. 考虑多种情况 [X=LCA(X,Y)] [Y=LCA(X,Y)] else void d ...
- [SPOJ]Count on a tree II(树上莫队)
树上莫队模板题. 使用欧拉序将树上路径转化为普通区间. 之后莫队维护即可.不要忘记特判LCA #include<iostream> #include<cstdio> #incl ...
- 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 ...
- 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 ...
- SPOJ COT2 Count on a tree II (树上莫队,倍增算法求LCA)
题意:给一个树图,每个点的点权(比如颜色编号),m个询问,每个询问是一个区间[a,b],图中两点之间唯一路径上有多少个不同点权(即多少种颜色).n<40000,m<100000. 思路:无 ...
- 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 ...
- SPOJ COT2 Count on a tree II (树上莫队)
题目链接:http://www.spoj.com/problems/COT2/ 参考博客:http://www.cnblogs.com/xcw0754/p/4763804.html上面这个人推导部分写 ...
随机推荐
- RDLC报表系列(四) 矩阵
继续接上一篇的内容,本文主要是讲矩阵的内容 用到的数据源如下: DataTable dt = new DataTable(); dt.Columns.Add("FiscalYear" ...
- js、jquery、css使用过程中学到的一些方法技巧
快速查看 1 动态创建script/link/style标签 2 在不适合使用iframe的情况下,让页面像iframe那样能分块滚动 3 鼠标在元素上时显示tip风格的提示信息 1.动态创建scr ...
- 卸载cloudera manager
卸载Cloudera-Manager sudo /usr/share/cmf/uninstall-cloudera-manager.sh 一直选择Yes 就好 卸载完成后,它会问你是否要将databa ...
- 响应式web之媒体查询(一)
HTML4和css2目前支持为不用的媒体类型设定专有的样式,如,一个页面在屏幕上时使用无衬线字体,而在打印时使用衬线字体.screen和print是两种已定义的媒体类型.媒体查询让样式表有更强的针对性 ...
- Ubuntu 13.04下安装Vmware tools 9.2.3
更新13.04后 VmwareTools安装会出现三个问题 找不到generic kernel headers头文件 编译vmci出错 编译vmhgfs出错 第一个问题是系统的文件位置换了,而VMTO ...
- 分享个人如何DIY网站的经验
对于一个接触过Web开发的IT人来说,一般都考虑过创建属于自己的网站,可能是定制自己特有风格的博客类网站,可能是私密的个人主页,也可能是展示自己开源工具的网站,当然,酝酿着做个商业网站来创业的人肯定也 ...
- svn常见问题汇总
has no ancestry information 经查,由于project/,01Dev/的权限被关闭了,把当前文件夹父目录(project/,01Dev/) 下的 .svn/ 目录删除就好了.
- vimTAB宽度等设置
10 set shiftwidth=4 11 set softtabstop=4 12 set textwidth=200 13 set nu 14 set autoindent 15 set noe ...
- C语言的本质(3)——整数的本质与运算
C语言的本质(3)--整数的本质与运算 计算机存储的最小单位是字节(Byte),一个字节通常是8个bit.C语言规定char型占一个字节的存储空间.如果这8个bit按无符号整数来解释,则取值范围是0~ ...
- mssql中得到当天数据的语句
一条例子: 关键语句: