Description

​ 神犇家门口种了一棵苹果树。苹果树作为一棵树,当然是呈树状结构,每根树枝连接两个苹果,每个苹果都可以沿着一条由树枝构成的路径连到树根,而且这样的路径只存在一条。由于这棵苹果树是神犇种的,所以苹果都发生了变异,变成了各种各样的颜色。我们用一个![img](file:///C:/DOCUME1/ADMINI1/LOCALS~1/Temp/msohtml1/01/clip_image002.gif)到n之间的正整数来表示一种颜色。树上一共有n个苹果。每个苹果都被编了号码,号码为一个1到n之间的正整数。我们用0代表树根。只会有一个苹果直接根。

有许许多多的人来神犇家里膜拜神犇。可神犇可不是随便就能膜拜的。前来膜拜神犇的人需要正确回答一个问题,才能进屋膜拜神犇。这个问题就是,从树上编号为u的苹果出发,由树枝走到编号为v的苹果,路径上经过的苹果一共有多少种不同的颜色(包括苹果u和苹果v的颜色)?不过神犇注意到,有些来膜拜的人患有色盲症。具体地说,一个人可能会认为颜色a就是颜色b,那么他们在数苹果的颜色时,如果既出现了颜色a的苹果,又出现了颜色b的苹果,这个人只会算入颜色b,而不会把颜色a算进来。

神犇是一个好人,他不会强人所难,也就会接受由于色盲症导致的答案错误(当然答案在色盲环境下也必须是正确的)。不过这样神犇也就要更改他原先数颜色的程序了。虽然这对于神犇来说是小菜一碟,但是他想考验一下你。你能替神犇完成这项任务吗?

Input

输入第一行为两个整数n和m,分别代表树上苹果的个数和前来膜拜的人数。

接下来的一行包含n个数,第i个数代表编号为i的苹果的颜色Coli。

接下来有n行,每行包含两个数x和y,代表有一根树枝连接了苹果x和y(或者根和一个苹果)。

接下来有m行,每行包含四个整数u、v、a和b,代表这个人要数苹果u到苹果v的颜色种数,同时这个人认为颜色a就是颜色b。如果a=b=0,则代表这个人没有患色盲症。

Output

输出一共m行,每行仅包含一个整数,代表这个人应该数出的颜色种数。

Sample Input

5 3

1 1 3 3 2

0 1

1 2

1 3

2 4

3 5

1 4 0 0

1 4 1 3

1 4 1 2

Sample Output

2

1

2

HINT

0<=x,y,a,b<=N

N<=50000

1<=U,V,Coli<=N

M<=100000


思路

树上莫队板子

直接网上搜树上莫队就可以了


#include<bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;

int n, m, cur = 0;
int top = 0, ind = 0, blosiz, blonum, root;
int res[N], p[N];
int fa[N][20], dep[N];
int c[N], st[N], dfn[N], bel[N];
bool vis[N]; struct Edge {
int v, nxt;
} E[N]; int head[N], cnt = 0; struct Query {
int u, v, a, b, id;
} q[N]; bool operator < (const Query &a, const Query &b) {
return bel[a.u] == bel[b.u] ? dfn[a.v] < dfn[b.v] : bel[a.u] < bel[b.u];
} void addedge(int u, int v) {
E[++cnt] = (Edge) {v, head[u]};
head[u] = cnt;
} int dfs(int u) {
int siz = 0;
dfn[u] = ++ind;
for (int i = 1; i <= 18; i++)
fa[u][i] = fa[fa[u][i - 1]][i - 1];
for (int i = head[u]; i; i = E[i].nxt) {
int v = E[i].v;
if (v == fa[u][0]) continue;
dep[v] = dep[u] + 1;
fa[v][0] = u;
siz += dfs(v);
if (siz >= blosiz) {
++blonum;
for (int k = 1; k <= siz; k++) {
bel[st[top--]] = blonum;
}
siz = 0;
}
}
st[++top] = u;
return siz + 1;
} int lca(int x, int y) {
if (dep[x] < dep[y]) swap(x, y);
int delta = dep[x] - dep[y];
for (int i = 0; i <= 18; i++) {
if ((delta >> i) & 1) {
x = fa[x][i];
}
}
if (x == y) return x;
for (int i = 18; i >= 0; i--) {
if (fa[x][i] != fa[y][i]) {
x = fa[x][i];
y = fa[y][i];
}
}
return fa[x][0];
} void reverse(int x) {
if (!vis[x]) {
vis[x] = 1;
if (++p[c[x]] == 1) ++cur;
} else {
vis[x] = 0;
if (--p[c[x]] == 0) --cur;
}
} void solve(int u, int v) {
while (u != v) {
if (dep[u] > dep[v]) {
reverse(u);
u = fa[u][0];
} else {
reverse(v);
v = fa[v][0];
}
}
} int main() {
#ifdef dream_maker
freopen("input.txt", "r", stdin);
#endif
scanf("%d %d", &n, &m);
blosiz = sqrt(n << 1);
for (int i = 1; i <= n; i++) scanf("%d", &c[i]);
for (int i = 1; i <= n; i++) {
int u, v;
scanf("%d %d", &u, &v);
if (!u) root = v;
if (!v) root = u;
if (u && v) {
addedge(u, v);
addedge(v, u);
}
}
dfs(root);
if (top) {
blonum++;
while (top) {
bel[st[top--]] = blonum;
}
}
for (int i = 1; i <= m; i++) {
scanf("%d %d %d %d", &q[i].u, &q[i].v, &q[i].a, &q[i].b);
if (dfn[q[i].u] > dfn[q[i].v]) swap(q[i].u, q[i].v);
q[i].id = i;
}
sort(q + 1, q + m + 1);
int t = lca(q[1].u, q[1].v);
solve(q[1].u, q[1].v);
reverse(t);
res[q[1].id] = cur - (p[q[1].a] && p[q[1].b] && q[1].a != q[1].b);
reverse(t);
for (int i = 2; i <= m; i++) {
solve(q[i - 1].u, q[i].u);
solve(q[i - 1].v, q[i].v);
t = lca(q[i].u, q[i].v);
reverse(t);
res[q[i].id] = cur - (p[q[i].a] && p[q[i].b] && q[i].a != q[i].b);
reverse(t);
}
for (int i = 1; i <= m; i++)
printf("%d\n", res[i]);
return 0;
}

BZOJ3757: 苹果树【树上莫队】的更多相关文章

  1. [BZOJ3757]苹果树(树上莫队)

    树上莫队共有三种写法: 1.按DFS序列分块,和普通莫队类似.常数大,不会被卡. 2.按块状树的方式分块.常数小,会被菊花图卡到O(n). 3.按[BZOJ1086]王室联邦的方式分块.常数小,不会被 ...

  2. 【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)

    2016-05-09 UPD:学习了新的DFS序列分块,然后发现这个东西是战术核导弹?反正比下面的树分块不知道要快到哪里去了 #include<cmath> #include<cst ...

  3. BZOJ.3757.苹果树(树上莫队)

    题面链接 /* 代码正确性不保证..(不过交了SPOJ没WA T了最后一个点) 在DFS序做莫队 当一个点不是另一个点的LCA时,需要加上它们LCA的贡献 */ #include <cmath& ...

  4. 【BZOJ-3757】苹果树 块状树 + 树上莫队

    3757: 苹果树 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1305  Solved: 503[Submit][Status][Discuss] ...

  5. 2018.09.16 bzoj3757: 苹果树(树上莫队)

    传送门 一道树上莫队. 先用跟bzoj1086一样的方法给树分块. 分完之后就可以莫队了. 但是两个询问之间如何转移呢? 感觉很难受啊. 我们定义S(u,v)" role="pre ...

  6. 【BZOJ3757】苹果树(树上莫队)

    点此看题面 大致题意: 每次问你树上两点之间路径中有多少种颜色,每次询问可能会将一种颜色\(a\)看成\(b\). 树上莫队 这题是一道树上莫队板子题. 毕竟求区间中有多少种不同的数是莫队算法的经典应 ...

  7. 树上莫队 wowow

    构建:像线性的莫队那样,依旧是按sqrt(n)为一块分块. int dfs(int x){ ; dfn[x]=++ind; ;i<=;i++) if (bin[i]<=deep[x]) f ...

  8. [BZOJ 3052] [wc2013] 糖果公园 【树上莫队】

    题目链接:BZOJ - 3052 题目分析 这道题就是非常经典的树上莫队了,并且是带修改的莫队. 带修改的莫队:将询问按照 左端点所在的块编号为第一关键字,右端点所在的块为第二关键字,位于第几次修改之 ...

  9. spoj COT2 - Count on a tree II 树上莫队

    题目链接 http://codeforces.com/blog/entry/43230树上莫队从这里学的,  受益匪浅.. #include <iostream> #include < ...

随机推荐

  1. Codeforces 388A - Fox and Box Accumulation

    388A - Fox and Box Accumulation 思路: 从小到大贪心模拟. 代码: #include<bits/stdc++.h> using namespace std; ...

  2. robotframework安装与配置--学习第一天

    刚刚入职公司,之前学的是Java+selenium自动化测试,但公司要求使用robot framework,所以找了些资料学习.刚开始觉得为什么不用java.python等开发语言+selenium做 ...

  3. ubuntu10.04 交叉编译 aria2 总结

    1) google之后,找到 这个 https://github.com/z24/pitv/tree/master/cross 的脚本, 觉得非常好. 于是准备用来进行编译 2) 安装交叉编译器 su ...

  4. 各种容器与服务器的区别与联系 Servlet容器 WEB容器 Java EE容器 应用服务器 WEB服务器 Java EE服务器

    转自:https://blog.csdn.net/tjiyu/article/details/53148174 各种容器与服务器的区别与联系 Servlet容器 WEB容器 Java EE容器 应用服 ...

  5. centos7: vsftpd安装及启动: ftp配置(以虚拟用户为例)

    centos7: vsftpd安装及启动: ftp配置 1安装: yum -y install vsftpd /bin/systemctl start vsftpd.service #启动 /bin/ ...

  6. EF学习-获取实体框架01

    实体框架由 EF 设计器(包含在 Visual Studio 中)和 EF Runtime(在 NuGet 上提供)组成. EF 设计器包含在 Visual Studio 中 最新版本的实体框架设计器 ...

  7. LeetCode--168--Excel表列名称

    问题描述: 给定一个正整数,返回它在 Excel 表中相对应的列名称. 例如, 1 -> A 2 -> B 3 -> C ... 26 -> Z 27 -> AA 28 ...

  8. Visio 入门教程

    最近做一个新项目,目前在需求确立阶段,所以每天任务是写文档讨论再修改.由于是云端架构设计,避免不了图形图表配合文字说明,需要制作 E-R 图.网络图.时序图.UML 类图等,对比其他可视化图表工具,V ...

  9. HDU-4850 Wow! Such String! (构造)

    Problem Description Recently, doge starts to get interested in a strange problem: whether there exis ...

  10. UVA-11490 Just Another Problem

    题目大意:一个由p*q个点组成的pxq点阵(构成一个矩形).从内层点中拿走两块正方形上的所有点,这两块正方形要边长相等,在位置上关于中线对称,并且还要使每一个正方形的上下左右剩余的点的层数相等.现在告 ...