【BZOJ-3757】苹果树 块状树 + 树上莫队
3757: 苹果树
Time Limit: 20 Sec Memory Limit: 256 MB
Submit: 1305 Solved: 503
[Submit][Status][Discuss]
Description
神犇家门口种了一棵苹果树。苹果树作为一棵树,当然是呈树状结构,每根树枝连接两个苹果,每个苹果都可以沿着一条由树枝构成的路径连到树根,而且这样的路径只存在一条。由于这棵苹果树是神犇种的,所以苹果都发生了变异,变成了各种各样的颜色。我们用一个到n之间的正整数来表示一种颜色。树上一共有n个果。苹每个苹果都被编了号码,号码为一个1到n之间的正整数。我们用0代表树根。只会有一个苹果直接根。
有许许多多的人来神犇家里膜拜神犇。可神犇可不是随便就能膜拜的。前来膜拜神犇的人需要正确回答一个问题,才能进屋膜拜神犇。这个问题就是,从树上编号为u的苹果出发,由树枝走到编号为v的苹果,路径上经过的苹果一共有多少种不同的颜色(包括苹果u和苹果v的颜色)?不过神犇注意到,有些来膜拜的人患有色盲症。具体地说,一个人可能会认为颜色a就是颜色b,那么他们在数苹果的颜色时,如果既出现了颜色a的苹果,又出现了颜色b的苹果,这个人只会算入颜色b,而不会把颜色a算进来。
神犇是一个好人,他不会强人所难,也就会接受由于色盲症导致的答案错误(当然答案在色盲环境下也必须是正确的)。不过这样神犇也就要更改他原先数颜色的程序了。虽然这对于神犇来说是小菜一碟,但是他想考验一下你。你能替神犇完成这项任务吗?
Input
Output
输出一共m行,每行仅包含一个整数,代表这个人应该数出的颜色种数。
Sample Input
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
1
2
HINT
Source
Solution
树上莫队裸题,下面来说说树上莫队
序列上的莫队没什么好说的,至于树上莫队,思想是一样的
对树DFS分块(详见 BZOJ-1086王室联邦哦),然后对询问排序,然后处理就好,那么就是具体的实现了
至于树分块,就是按照DFS时间戳去搞,所以询问排序的第一关键字就是所在的块,第二关键字就是时间戳
至于如何把树上的一条路径,转化为一端区间?
首先我们设$S(u,v)$表示$u-v$的路径上的点集,$LCA(u,v)$表示两点的最近公共祖先,$root$为树根
$xor$为集合的对称差,即 只属于其中一个集合,而不属于另一个集合的元素组成的集合
那么发现$S(u,v)=S(root,u) xor S(root,v) xor LCA(u,v)$ (不懂见下图哦)
就是节点出现两次消掉
再有$T(u,v)=S(root, v) xor S(root, u)$
观察将询问$curV$移动到$targetV$前后$T(curV, curU)$变化:
$T(curV, curU)=S(root, curV) xor S(root, curU)$
$T(targetV, curU)=S(root, targetV) xor S(root, curU)$
取对称差:
$T(curV, curU) xor T(targetV, curU)= (S(root, curV) xor S(root, curU)) xor (S(root, targetV) xor S(root, curU))$
由于对称差的交换律、结合律:
$T(curV, curU) xor T(targetV, curU)= S(root, curV) xorS(root, targetV)$
两边同时$xor T(curV, curU)$:
$T(targetV, curU)= T(curV, curU) xor S(root, curV) xor S(root, targetV)$
$T(targetV, curU)=T(curV, curU) xor T(curV, targetV)$
也就是说,更新的时候,$xor T(curV, targetV)$就行了。

Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int read()
{
int x=;char ch=getchar();
while(ch<''||ch>'') ch=getchar();
while(ch>=''&&ch<='') {x=x*+ch-'';ch=getchar();}
return x;
}
#define maxn 50100
#define maxq 100100
int n,m,fk,knum,ans,root;
struct Edgenode{int to,next;}edge[maxn<<];
int head[maxn],cnt=;
void add(int u,int v)
{cnt++;edge[cnt].next=head[u];head[u]=cnt;edge[cnt].to=v;}
void insert(int u,int v)
{add(u,v); add(v,u);}
int deep[maxn],father[maxn][],dfsx,stack[maxn],top,rt[maxn],an[maxq],p[maxn];
struct Pointnode{int dfs,col;}po[maxn];
struct Asknode
{
int a,b,u,v,id;
bool operator < (const Asknode & A) const
{
if(rt[u]==rt[A.u]) return po[v].dfs<po[A.v].dfs;
else return rt[u]<rt[A.u];
}
}q[maxq];
bool visit[maxn];
int DFS(int now)
{
int size=;
po[now].dfs=++dfsx;
for (int i=; i<=; i++)
if (deep[now]>=(<<i))
father[now][i]=father[father[now][i-]][i-];
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=father[now][])
{
deep[edge[i].to]=deep[now]+;
father[edge[i].to][]=now;
size+=DFS(edge[i].to);
if (size>=fk)
{
knum++;
for(int j=; j<=size; j++)
rt[stack[top--]]=knum;
size=;
}
}
stack[++top]=now;
return size+;
}
int LCA(int x,int y)
{
if (deep[x]<deep[y]) swap(x,y);
int dd=deep[x]-deep[y];
for (int i=; i<=; i++)
if (dd&(<<i) && dd>=(<<i)) x=father[x][i];
for (int i=; i>=; i--)
if (father[x][i]!=father[y][i])
x=father[x][i],y=father[y][i];
if (x==y) return x; else return father[x][];
}
void reserv(int x)
{
if (!visit[x]) {visit[x]=; p[po[x].col]++; if (p[po[x].col]==) ans++;}
else {visit[x]=; p[po[x].col]--; if (p[po[x].col]==) ans--;}
}
void work(int u,int v)
{
while (u!=v)
if (deep[u]>deep[v]) reserv(u),u=father[u][];
else reserv(v),v=father[v][];
}
int main()
{
n=read(),m=read(); fk=sqrt(n);
for (int i=; i<=n; i++) po[i].col=read();
for (int u,v,i=; i<=n; i++)
{
u=read(),v=read();
if (!u) root=v;
else if (!v) root=u;
else insert(u,v);
}
DFS(root);
knum++;
while (top) rt[stack[top--]]=knum;
for (int i=; i<=m; i++)
{
q[i].u=read();q[i].v=read();q[i].a=read();q[i].b=read();q[i].id=i;
if (po[q[i].u].dfs>po[q[i].v].dfs) swap(q[i].u,q[i].v);
}
sort(q+,q+m+);
int T=LCA(q[].u,q[].v);
work(q[].u,q[].v); reserv(T); an[q[].id]=ans;
if (p[q[].a] && p[q[].b] && q[].a!=q[].b) an[q[].id]--;
reserv(T);
for (int i=; i<=m; i++)
{
work(q[i-].u,q[i].u);
work(q[i-].v,q[i].v);
T=LCA(q[i].u,q[i].v);
reserv(T); an[q[i].id]=ans;
if(p[q[i].a] && p[q[i].b] && q[i].a!=q[i].b) an[q[i].id]--;
reserv(T);
}
for (int i=; i<=m; i++) printf("%d\n",an[i]);
return ;
}
【BZOJ-3757】苹果树 块状树 + 树上莫队的更多相关文章
- BZOJ.3052.[WC2013]糖果公园(树上莫队 带修改莫队)
题目链接 BZOJ 当然哪都能交(都比在BZOJ交好),比如UOJ #58 //67376kb 27280ms //树上莫队+带修改莫队 模板题 #include <cmath> #inc ...
- BZOJ 4129: Haruna’s Breakfast [树上莫队 分块]
传送门 题意: 单点修改,求一条链的mex 分块维护权值,$O(1)$修改$O(S)$求mex...... 带修改树上莫队 #include <iostream> #include < ...
- bzoj 3585 mex - 线段树 - 分块 - 莫队算法
Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. Input 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问 ...
- bzoj 4129 Haruna’s Breakfast 树上莫队
按照dfs序分块,莫队乱搞 再套个权值分块 #include<cstdio> #include<iostream> #include<cstring> #inclu ...
- BZOJ 3052: [wc2013]糖果公园 | 树上莫队
题目: UOJ也能评测 题解 请看代码 #include<cstdio> #include<algorithm> #include<cstring> #includ ...
- 【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)
2016-05-09 UPD:学习了新的DFS序列分块,然后发现这个东西是战术核导弹?反正比下面的树分块不知道要快到哪里去了 #include<cmath> #include<cst ...
- [BZOJ 3052] [wc2013] 糖果公园 【树上莫队】
题目链接:BZOJ - 3052 题目分析 这道题就是非常经典的树上莫队了,并且是带修改的莫队. 带修改的莫队:将询问按照 左端点所在的块编号为第一关键字,右端点所在的块为第二关键字,位于第几次修改之 ...
- [BZOJ3757]苹果树(树上莫队)
树上莫队共有三种写法: 1.按DFS序列分块,和普通莫队类似.常数大,不会被卡. 2.按块状树的方式分块.常数小,会被菊花图卡到O(n). 3.按[BZOJ1086]王室联邦的方式分块.常数小,不会被 ...
- BZOJ3757: 苹果树【树上莫队】
Description 神犇家门口种了一棵苹果树.苹果树作为一棵树,当然是呈树状结构,每根树枝连接两个苹果,每个苹果都可以沿着一条由树枝构成的路径连到树根,而且这样的路径只存在一条.由于这棵苹果树 ...
随机推荐
- php中创建和调用webservice接口示例
php中创建和调用webservice接口示例 这篇文章主要介绍了php中创建和调用webservice接口示例,包括webservice基本知识.webservice服务端例子.webservi ...
- codevs 1033 蚯蚓的游戏问题
Description 在一块梯形田地上,一群蚯蚓在做收集食物游戏.蚯蚓们把梯形田地上的食物堆积整理如下: a(1,1) a(1,2)…a(1,m) a(2,1) a(2,2) a(2,3)…a ...
- Validate Binary Search Tree
Validate Binary Search Tree Given a binary tree, determine if it is a valid binary search tree (BST) ...
- SQL Server对Xml字段的操作
T-Sql操作Xml数据 一.前言 SQL Server 2005 引入了一种称为 XML 的本机数据类型.用户可以创建这样的表,它在关系列之外还有一个或多个 XML 类型的列:此外,还允许带有变量和 ...
- ehcache2.8.3入门示例:hello world
一.pom.xml 依赖项 <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehc ...
- HP DL60 Gen9 安装CentOS 6.5
由于Gen 9的VID中自带RETHAT 5.X-7.0的驱动, 所以不需要制作驱动盘. 一, 准备工作 1. 制作 CentOS安装盘 2. 配置阵列, 开机过了自检后按F10. 自己看着配... ...
- 基于ASP.NET MVC的热插拔模块式开发框架(OrchardNoCMS)--瘦身计划
Orchard CMS是针对CMS开发的,对于很多开发需求来说,内容管理这块儿可能并不需要,而需要它的模块式开发模式.所以我这里通过对OrchardCMS进行瘦身,去除 内容管理部分的内容,保留简单的 ...
- 面向对象的PHP
类的实例(包括继承) <?php // 父类 class Animal { public $name; public $age; // 构造函数,使用new操作符生成实例的时候自动调用 func ...
- Linux之我见
Linux哲学之美 linux就像是一个哲学的最佳实践.如果非要对它评价,我真的不知道该怎么赞叹,我只能自豪的说着:“linux的美丽简直让人沉醉.” 我只能说是我处在linux学习的修炼之路上的一个 ...
- .Net相关
Lucene 全文搜索 http://lucenenet.apache.org/ Memcached 分布式缓存 http://memcached.org/ selenium UI自动化测试 http ...