题意

给定一个n个节点的树,每个节点表示一个整数,问u到v的路径上有多少个不同的整数。

n=40000,m=100000

Sol

树上莫队模板题

# include <bits/stdc++.h>
# define RG register
# define IL inline
# define Fill(a, b) memset(a, b, sizeof(a))
using namespace std;
const int _(1e5 + 5);
typedef long long ll; IL int Input(){
RG int x = 0, z = 1; RG char c = getchar();
for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x * z;
} int n, m, first[_], cnt, w[_], o[_], len;
int dfn[_], st[20][_], lg[_], deep[_], idx, fa[_];
int S[_], bl[_], blo, num, ans[_], sum[_], vis[_], Ans;
struct Edge{
int to, next;
} edge[_];
struct Query{
int l, r, id; IL int operator <(RG Query B) const{
return bl[l] == bl[B.l] ? dfn[r] < dfn[B.r] : bl[l] < bl[B.l];
}
} qry[_]; IL void Add(RG int u, RG int v){
edge[cnt] = (Edge){v, first[u]}, first[u] = cnt++;
} IL void Dfs(RG int u){
dfn[u] = ++idx, st[0][idx] = u; RG int l = S[0];
for(RG int e = first[u]; e != -1; e = edge[e].next){
RG int v = edge[e].to;
if(dfn[v]) continue;
deep[v] = deep[u] + 1, fa[v] = u;
Dfs(v);
if(S[0] - l >= blo) for(++num; S[0] != l; --S[0]) bl[S[S[0]]] = num;
st[0][++idx] = u;
}
S[++S[0]] = u;
} IL void Chk(RG int &x, RG int u, RG int v){
x = deep[u] < deep[v] ? u : v;
} IL int LCA(RG int u, RG int v){
u = dfn[u], v = dfn[v];
if(u > v) swap(u, v);
RG int log2 = lg[v - u + 1], t;
Chk(t, st[log2][u], st[log2][v - (1 << log2) + 1]);
return t;
} IL void Update(RG int x){
if(vis[x]) --sum[w[x]], Ans -= (!sum[w[x]]);
else Ans += (!sum[w[x]]), ++sum[w[x]];
vis[x] ^= 1;
} IL void Modify(RG int u, RG int v){
while(u != v){
if(deep[u] > deep[v]) swap(u, v);
Update(v), v = fa[v];
}
} int main(RG int argc, RG char* argv[]){
len = n = Input(), m = Input(), blo = sqrt(n);
for(RG int i = 1; i <= n; ++i) o[i] = w[i] = Input(), first[i] = -1;
sort(o + 1, o + len + 1), len = unique(o + 1, o + len + 1) - o - 1;
for(RG int i = 1; i <= n; ++i) w[i] = lower_bound(o + 1, o + len + 1, w[i]) - o;
for(RG int i = 1, u, v; i < n; ++i)
u = Input(), v = Input(), Add(u, v), Add(v, u);
Dfs(1);
if(S[0]) for(++num; S[0]; --S[0]) bl[S[S[0]]] = num;
for(RG int i = 2; i <= idx; ++i) lg[i] = lg[i >> 1] + 1;
for(RG int j = 1; j <= lg[idx]; ++j)
for(RG int i = 1; i + (1 << j) - 1 <= idx; ++i)
Chk(st[j][i], st[j - 1][i], st[j - 1][i + (1 << (j - 1))]);
for(RG int i = 1; i <= m; ++i){
qry[i] = (Query){Input(), Input(), i};
if(dfn[qry[i].l] > dfn[qry[i].r]) swap(qry[i].l, qry[i].r);
}
sort(qry + 1, qry + m + 1);
RG int lca = LCA(qry[1].l, qry[1].r);
Modify(qry[1].l, qry[1].r);
Update(lca), ans[qry[1].id] = Ans, Update(lca);
for(RG int i = 2; i <= m; ++i){
Modify(qry[i - 1].l, qry[i].l), Modify(qry[i - 1].r, qry[i].r);
lca = LCA(qry[i].l, qry[i].r);
Update(lca), ans[qry[i].id] = Ans, Update(lca);
}
for(RG int i = 1; i <= m; ++i) printf("%d\n", ans[i]);
return 0;
}

SPOJ:COT2 Count on a tree II的更多相关文章

  1. SPOJ 10707 COT2 - Count on a tree II

    思路 树上莫队的题目 每次更新(u1,u2)和(v1,v2)(不包括lca)的路径,最后单独统计LCA即可 代码 #include <cstdio> #include <cstrin ...

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

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

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

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

  5. 【SPOJ10707】 COT2 Count on a tree II

    SPOJ10707 COT2 Count on a tree II Solution 我会强制在线版本! Solution戳这里 代码实现 #include<stdio.h> #inclu ...

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

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

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

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

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

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

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

随机推荐

  1. openstack的部署与运维

    来公司几个月了,除了搭建了kvm虚拟机,使用3台虚拟机组合成一个openstack的网络环境.还没有正式将openstack搭建起来过.时间都在开发web程序.不过openstack也是要学习的.只能 ...

  2. 2016级算法第三次上机-B.Bamboo和巧克力工厂

    B Bamboo和巧克力工厂 分析 三条流水线的问题,依然是动态规划,但是涉及的切换种类比较多.比较易于拓展到n条流水线的方式是三层循环,外层是第k个机器手,里面两层代表可切换的流水线 核心dp语句: ...

  3. Linux 内存监控

    1.按照内存使用方式排序 top 之后使用 shift + m 那么top按照内存使用从大到小进行排列,使用 shift + P 表示按照CPU进行排序. bigfish 1118m 438m 30m ...

  4. CoreText 图文混排

    基本原理 https://www.cnblogs.com/purple-sweet-pottoes/p/5109413.html CoreText(一):基本用法  https://blog.csdn ...

  5. 编写高质量代码:Web前端开发修炼之道(四)

    这一节是继上一节高质量的Javascript 7)编程实用技巧 1:弹性 从 一个标签区和内容区的实例(就是点击不同的标签菜单显示不同的内容块)来说明不需要每个tabmenu都设置onclick事件, ...

  6. 阿里云Centos下安装nginx之后外网无法访问

    centos 7.4 nginx1-14.0编译安装 curl 127.0.0.1 可以请求到 index.html curl local 可以请求到 index.html http://ip/ 无法 ...

  7. web.py简易示例

    http://webpy.org/cookbook/index.zh-cn code.py import web urls = ( '/', 'index' ) class index: def GE ...

  8. C#几种常用的加密方式

    一.AES加密算法   AES算法基于排列和置换运算.排列是对数据重新进行安排,置换是将一个数据单元替换为另一个.AES 使用几种不同的方法来执行排列和置换运算.    AES是一个迭代的.对称密钥分 ...

  9. (转)Linux-HA实战(1)— Heartbeat安装

    原文:http://blog.csdn.net/liaomin416100569/article/details/76087448-------centos7源代码编译安装heartbeat 原文:h ...

  10. 【ExtJS】简单布局应用

    前几天学习了ExtJS的各种布局后,以下就是各种实践,从简单做起. 实现目的: 一个提交表单页,一个显示信息页,表单为个人基本资料输入,显示页为基本信息展示. 内容: 总体布局为border布局,展示 ...