【BZOJ】3757 苹果树

题意:n个节点的树,每个点有一种颜色。现有m种询问,每次询问x y a b表示x到y的路径上颜色的种数且a颜色看成b颜色。(n<=50000, m<=100000)

#include <bits/stdc++.h>
using namespace std;
const int N=50005;
int ihead[N], cnt, id[N], blo[N], f[N][16], dep[N], cal[N], col[N], st[N], n, m, Ans[N], ans, ID;
struct E { int next, to; }e[N<<1];
struct Q { int x, y, a, b, id; }q[N*2];
bool cmp(const Q &a, const Q &b) { return blo[a.x]==blo[b.x]?id[a.y]<id[b.y]:blo[a.x]<blo[b.x]; }
void add(int x, int y) { e[++cnt]=(E){ihead[x], y}; ihead[x]=cnt; e[++cnt]=(E){ihead[y], x}; ihead[y]=cnt; }
void dfs(int x) {
	id[x]=++ID;
	for(int i=1; i<=15; ++i) f[x][i]=f[f[x][i-1]][i-1];
	for(int i=ihead[x]; i; i=e[i].next) if(e[i].to!=f[x][0]) { dep[e[i].to]=dep[x]+1; f[e[i].to][0]=x; dfs(e[i].to); }
}
int LCA(int x, int y) {
	if(dep[x]<dep[y]) swap(x, y);
	int d=dep[x]-dep[y];
	for(int i=15; i>=0; --i) if((d>>i)&1) x=f[x][i]; if(x==y) return x;
	for(int i=15; i>=0; --i) if(f[x][i]!=f[y][i]) x=f[x][i], y=f[y][i];
	return f[x][0];
}
void update(int x) {
	if(st[x]) { if(!(--cal[col[x]])) --ans; }
	else { if(!cal[col[x]]) ++ans; ++cal[col[x]]; }
	st[x]=!st[x];
}
void move(int x, int y) {
	while(x!=y)
		if(dep[x]>dep[y]) update(x), x=f[x][0];
		else update(y), y=f[y][0];
}
bool check(int a, int b) { return cal[a] && cal[b] && a!=b; } //a!=b
void pre() {
	dfs(1);
	for(int i=1; i<=m; ++i) { scanf("%d%d%d%d", &q[i].x, &q[i].y, &q[i].a, &q[i].b), q[i].id=i; if(id[q[i].x]>id[q[i].y]) swap(q[i].x, q[i].y); }
	int sq=sqrt(n+0.5);
	for(int i=1; i<=n; ++i) blo[i]=(i-1)/sq;
	sort(q+1, q+1+m, cmp);
	q[0].x=q[0].y=1;
}
void work() {
	for(int i=1; i<=m; ++i) {
		move(q[i-1].x, q[i].x); move(q[i-1].y, q[i].y);
		int lca=LCA(q[i].x, q[i].y);
		update(lca);
		Ans[q[i].id]=ans;
		if(check(q[i].a, q[i].b)) --Ans[q[i].id];
		update(lca);
	}
	for(int i=1; i<=m; ++i) printf("%d\n", Ans[i]);
}
int main() {
	scanf("%d%d", &n, &m);
	for(int i=1; i<=n; ++i) scanf("%d", &col[i]);
	for(int i=1; i<=n; ++i) {
		int x, y; scanf("%d%d", &x, &y);
		if(!x || !y) continue;
		add(x, y);
	}
	pre();
	work();
	return 0;
}

  

树上分块= =

首先一开始就强行yy到了dfs序然后分块,后来不知什么鬼我自己不相信这样做能过这题(因为我一开始理解错啦= =假如固定了l,那么r走过的节点数是均摊O(n)的啊= =最多为2n次(进来又出去))

发现题解就是我一开始想的那样= =

可是我忽略了一个问题有木有!在更新lca的时候可能会出问题!自己画图可以得知!反正如果特判的话很难写的样子?

听说vfk神犇有题解我就去膜拜了下= =跪烂

首先设$S(u, v)$表示$u$到$v$路径上的节点集合。令$+$操作表示元素的模2加(即出现次数的模2加法,即异或= =,就是出现两次的就去掉)

容易得到$S(u, v) = S(root, u) + S(root, v) + lca(u, v)$

lca就是最麻烦的,vfk给出了一种巧妙的解法:

设$T(u, v) = S(root, u) + S(root, v)$

则设$u‘$表示$u$要到达的目的地:

$$T(u, v) + T(u‘, v) = S(u, root) + S(u‘, root) + S(v, root) + S(v, root)$$

$$T(u‘, v) = T(u, u‘) + T(u, v)$$

那么我们要从$T(u, v)$转移到$T(u‘, v)$只需要走一次$T(u, u‘)$上的点就行辣!(注意踢掉lca)

而不选lca可以直接用向上爬的方法做= =很简单哒= =

然后计数颜色就开个计数器就行辣= =

然后就没辣= =

时间: 2024-11-29 02:59:45

【BZOJ】3757 苹果树的相关文章

bzoj 3757: 苹果树(树上莫队)

3757: 苹果树 Time Limit: 20 Sec  Memory Limit: 256 MB Submit: 1327  Solved: 510 [Submit][Status][Discuss] Description 神犇家门口种了一棵苹果树.苹果树作为一棵树,当然是呈树状结构,每根树枝连接两个苹果,每个苹果都可以沿着一条由树枝构成的路径连到树根,而且这样的路径只存在一条.由于这棵苹果树是神犇种的,所以苹果都发生了变异,变成了各种各样的颜色.我们用一个1到n之间的正整数来表示一种颜色

bzoj 3757 苹果树(树上莫队算法)

[题意] 有若干个询问,询问路径u,v上的颜色总数,另外有要求a,b,意为将a颜色看作b颜色. [思路] vfk真是神系列233. Quote: 用S(v, u)代表 v到u的路径上的结点的集合. 用root来代表根结点,用lca(v, u)来代表v.u的最近公共祖先. 那么 S(v, u) = S(root, v) xor S(root, u) xor lca(v, u) 其中xor是集合的对称差. 简单来说就是节点出现两次消掉. lca很讨厌,于是再定义 T(v, u) = S(root,

BZOJ 3757 苹果树 树上莫队

题目大意:给出一棵树,问任意两点之间有多少种不同的颜色,一个人可能会有色盲,会将A和B当成一种颜色. 思路:比较裸的树上莫队,写出来之后,很慢,怀疑是分块的缘故,然后果断找了当年比赛的标称交上去,瞬间rk1,大概看了一眼,他好像是直接用DFS序+曼哈顿距离最小生成树搞的,为什么会比分块快? 昨天下午看到这个题之后就一直在研究树上莫队的正确姿势,然后先写了树分块,后来看了很多牛人的SPOJ COT2的题解,后来又和同学探讨了好久才弄明白. 首先先将树分块,然后把区间排序,按照第一权值为左端点所在块

bzoj 3757 树上莫队

感谢以下文章作者: http://blog.csdn.net/kuribohg/article/details/41458639 http://vfleaking.blog.163.com/blog/static/174807634201311011201627/ http://blog.csdn.net/jiangyuze831/article/details/41476865 http://hzwer.com/5259.html 做了树上的莫队,感觉对这个算法的思想理解更深了 先分块,不论怎

BZOJ - 3757 树上莫队解决离线路径问题 &amp; 学习心得

题意:给你一棵树,求u,v最短路径的XXX(本题是统计权值种类) 今天课上摸鱼学了一种有意思的处理路径方式(其实是链式块状树翻车了看别的),据说实际运行跑的比XX记者还快 大概就是像序列莫队那样 首先是对暴力查询的优化 第一关键字是块(树上分块),第二关键字是dfs序,这样保证了离线操作的下界最优 其次是转移的优化 我把大佬的话再转述一遍: 设\(S(u,v)\):\(u-v\)最短路径所覆盖的点集 \(S(u,v)=S(root,u)⊕S(root,v)⊕lca(u,v)\) 记\(T(u,v

【BZOJ】【3757】苹果树

树分块 orz HZWER http://hzwer.com/5259.html 不知为何我原本写的倍增求LCA给WA了……学习了HZWER的倍增新姿势- 树上分块的转移看vfk博客的讲解吧……(其实是先指向hzwer博客,再跳转vfk和KoribohG……) vfk讲的很详细,重点就在于转移的时候无视lca,只有在计算答案的时候临时加进来lca,算完答案再把lca去掉. 1 /***********************************************************

【BZOJ】3052: [wc2013]糖果公园

http://www.lydsy.com/JudgeOnline/problem.php?id=3052 题意:n个带颜色的点(m种),q次询问,每次询问x到y的路径上sum{w[次数]*v[颜色]},可以单点修改颜色.(n, m, q<=100000) #include <bits/stdc++.h> using namespace std; const int N=100005, M=100005; typedef long long ll; inline int getint()

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

3757: 苹果树 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1305  Solved: 503[Submit][Status][Discuss] Description 神犇家门口种了一棵苹果树.苹果树作为一棵树,当然是呈树状结构,每根树枝连接两个苹果,每个苹果都可以沿着一条由树枝构成的路径连到树根,而且这样的路径只存在一条.由于这棵苹果树是神犇种的,所以苹果都发生了变异,变成了各种各样的颜色.我们用一个到n之间的正整数来表示一种颜色.树上

bzoj 3052: [wc2013]糖果公园(带修改的树上莫队)

3052: [wc2013]糖果公园 Time Limit: 200 Sec  Memory Limit: 512 MB Submit: 892  Solved: 425 [Submit][Status][Discuss] Description Input Output Sample Input Sample Input Sample Output 84 131 27 84 HINT Source [Submit][Status][Discuss] 题解:bzoj 2120 和 bzoj 37