题面

给定一棵树,有点权

每次询问给出一些点对,求这些点对之间的路径的并集上不同权值的个数,以及这些权值的$mex$

思路

先考虑只有一对点对,只询问不同权值个数的问题:树上莫队模板题

然后加个$mex$:还是可以树上莫队

然后加入多组点对:这下不能莫队了

我们考虑另一种和莫队相似的算法:分块,在树上就是树分块

我们发现树分块要处理只有不同权值的问题的话,配合$bitset$食用会很好

预处理每个块顶到它的直系父亲块顶这条路径上的bitset

对于一个点对$(l,r)$,分开处理两条只有上下的链:$(l,lca)$和$(r,lca)$

链中间的部分跳块,两边的部分暴力跳

然后我们发现树分块+bitset可以处理多组点对的问题,因为bitset可以按位或起来

然后我们又发现bitset有一个叫find_first的东西,于是mex也解决了

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cassert>
#include<bitset>
#include<queue>
#define last DEEP_DARK_FANTASY
#define ll long long
using namespace std;
inline int read(){
int re=0,flag=1;char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') flag=-1;
ch=getchar();
}
while(isdigit(ch)) re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
return re*flag;
}
int n,m,op;
int first[100010],cnte=-1;
struct edge{
int to,next;
}a[200010];int w[100010];
inline void add(int u,int v){
a[++cnte]=(edge){v,first[u]};first[u]=cnte;
a[++cnte]=(edge){u,first[v]};first[v]=cnte;
}
int dep[100010],siz[100010],son[100010],top[100010],fa[100010],dfn[100010],clk;
void dfs1(int u,int f){//树剖lca
int i,v;
fa[u]=f;
dep[u]=dep[f]+1;
siz[u]=1;son[u]=0;
for(i=first[u];~i;i=a[i].next){
v=a[i].to;if(v==f) continue;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[son[u]]<siz[v]) son[u]=v;
}
}
void dfs2(int u,int t){
int i,v;
top[u]=t;dfn[u]=++clk;
if(son[u]) dfs2(son[u],t);
for(i=first[u];~i;i=a[i].next){
v=a[i].to;if(v==son[u]||v==fa[u]) continue;
dfs2(v,v);
}
}
int lca(int l,int r){
while(top[l]!=top[r]){
if(dep[top[l]]>dep[top[r]]) swap(l,r);
r=fa[top[r]];
}
if(dep[l]>dep[r]) swap(l,r);
return l;
}
bitset<100010>tmp,st[150][150];
int id[100010],vis[100010],cntd,pos[100010],belong[100010],pre[100010],blk;
void getst(int u){
if(!u||vis[u]) return;
vis[u]=1;
id[u]=++cntd;
tmp.reset();
while(u){
tmp[w[u]]=1;
if(pre[u]==u){
st[cntd][belong[u]]=tmp;
}
u=fa[u];
}
}
void dfs(int u,int f){
int i,v;
for(i=first[u];~i;i=a[i].next){
v=a[i].to;if(v==f) continue;
if(belong[u]==belong[v]) pre[v]=pre[u];
else pre[v]=v;
dfs(v,u);
}
if(pre[u]==u) getst(fa[u]);
}
void build(){//树分块
int i,u,v;
for(i=1;i<=n;i++) pos[i]=i;
random_shuffle(pos+1,pos+n+1);//神秘的树分块技巧:随机块顶......
blk=min(n,150);
queue<int>q;
for(i=1;i<=blk;i++){
belong[pos[i]]=i;
q.push(pos[i]);
}
while(!q.empty()){
int u=q.front();q.pop();
for(i=first[u];~i;i=a[i].next){
v=a[i].to;if(belong[v]) continue;
q.push(v);belong[v]=belong[u];
}
}
pre[1]=1;
dfs(1,0);
}
inline void jump(int u,int v){
if(dep[u]<dep[v]) return;
while(u!=v){
tmp[w[u]]=1;
u=fa[u];
}
tmp[w[u]]=1;
}
inline void solve(int u,int t){
if(belong[u]==belong[t]){
jump(u,t);
return;
}
jump(u,pre[u]);
int v=fa[pre[u]],x=0;
while(dep[pre[v]]>=dep[t]){
x=belong[v];
v=fa[pre[v]];
}
if(x) tmp|=st[id[fa[pre[u]]]][x];
jump(v,t);
}
int main(){
memset(first,-1,sizeof(first));
n=read();m=read();op=read();
int i,t3,t1,t2,j,last=0;
for(i=1;i<=n;i++) w[i]=read();
for(i=1;i<n;i++){
t1=read();t2=read();
add(t1,t2);
}
dfs1(1,0);
dfs2(1,1);
build();
while(m--){
j=read();tmp.reset();
for(i=1;i<=j;i++){
t1=read();t2=read();
t1^=(last*op);
t2^=(last*op);
t3=lca(t1,t2);
solve(t1,t3);
solve(t2,t3);
}
t1=tmp.count();
tmp.flip();
t2=tmp._Find_first();
printf("%d %d\n",t1,t2);
last=t1+t2;
}
}

种树 by yoyoball [树分块+bitset]的更多相关文章

  1. 洛谷 P6177 - Count on a tree II/【模板】树分块(树分块)

    洛谷题面传送门 好家伙,在做这道题之前我甚至不知道有个东西叫树分块 树分块,说白了就是像对序列分块一样设一个阈值 \(B\),然后在树上随机撒 \(\dfrac{n}{B}\) 个关键点,满足任意一个 ...

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

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

  3. 2015北京网络赛 J Clarke and puzzle 求五维偏序 分块+bitset

    Clarke and puzzle Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://hihocoder.com/contest/acmicpc20 ...

  4. [BZOJ 1086] [SCOI2005] 王室联邦 【树分块】

    题目链接:BZOJ - 1086 题目分析 这道题要求给树分块,使得每一块的大小在 [B, 3B] 之间,并且可以通过一个块外的节点(块根)使得整个块联通. 那么我们使用一种 DFS,维护一个栈,DF ...

  5. hihocoder1236(北京网络赛J):scores 分块+bitset

    北京网络赛的题- -.当时没思路,听大神们说是分块+bitset,想了一下发现确实可做,就试了一下,T了好多次终于过了 题意: 初始有n个人,每个人有五种能力值,现在有q个查询,每次查询给五个数代表查 ...

  6. 洛谷.2590.[ZJOI2008]树的统计(树分块)

    题目链接 Update:这种分块写法...可以被卡掉啊... 好像没有靠谱的树分块写法... /* 对树上节点进行分块,每个点记录dep,fa,val,Max,Sum,Max,Sum表示当前点在该块内 ...

  7. BZOJ.3720.Gty的妹子树(树分块)

    题目链接 洛谷上惨遭爆零是为什么.. 另外这个树分块算法是假的. /* 插入删除只涉及一个数,故每次可以枚举一遍,而不是重构完后sort */ #include<cmath> #inclu ...

  8. hdu 4366 Successor - CDQ分治 - 线段树 - 树分块

    Sean owns a company and he is the BOSS.The other Staff has one Superior.every staff has a loyalty an ...

  9. 【bzoj2741】[FOTILE模拟赛]L 可持久化Trie树+分块

    题目描述 FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor A ...

随机推荐

  1. 浅谈React虚拟DOM

    为什么要使用虚拟DOM 因为浏览器的DOM渲染是非常消耗性能的,很低效,我们使用虚拟DOM是为了提高DOM的渲染性能: 什么是虚拟DOM 虚拟DOM就是把真实的DOM树通过createElement转 ...

  2. Spark-源码-Spark-Submit 任务提交

    Spark 版本:1.3 调用shell, spark-submit.sh args[] 首先是进入 org.apache.spark.deploy.SparkSubmit 类中调用他的 main() ...

  3. 【Hbase二】环境搭建

    此笔记仅用于作者记录复习使用,如有错误地方欢迎留言指正,作者感激不尽,如有转载请指明出处 Hbase环境搭建 Hbase环境搭建 hadoop为HA的Hbase配置 Zookeeper集群的正常部署并 ...

  4. 5.Python的语言特点

    前言   Python有哪些语言特点?可以列出的特点很多,例如,<Python核心编程>第二版列出了十多条特点.本文的三个特点是笔者学习Python的体会,其他特点有体会之后再写,笔者是这 ...

  5. Python学习手册之Python异常和文件

    在上一篇文章中,我们介绍了 Python 的函数和模块,现在我们介绍 Python 中的异常和文件. 查看上一篇文章请点击:https://www.cnblogs.com/dustman/p/9963 ...

  6. Kubernetes-创建集群(四)

    Kubernetes可以运行在多种平台,从笔记本到云服务商的虚拟机,再到机架上的裸机服务器.要创建一个Kubernetes集群,根据不同的场景需要做的也不尽相同,可能是运行一条命令,也可能是配置自己定 ...

  7. 集合--数据结构与算法JavaScript描述(9)

    集合 Set 概念 (跟高中时数学课上学的集合几乎一模一样哦哈哈) 集合是一种包含不同元素的数据结构. 集合中的元素称为成员. 集合的两个最重要的特性: 集合中的成员是无序的. 集合中不允许相同成员存 ...

  8. HTC Vive小场地与大场景空间的解决方案

    本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/52780621 作者:car ...

  9. oracle 11g XE 学习版添加scott用户方法全步骤

    安装企业版的orcale是不是太费时费力了?若只是学习用途的话,不妨试试轻便版的XE版本,同样是官网下载的,但是这个安装起来比完整版简便多了. 首先,你得先安装好orcale 11g XE 版本:(这 ...

  10. linux-clone-ip处理办法

    vim /etc/udev/rules.d/70-persistent-net.rules 步骤1:#将eth0相关的文件给删除 步骤2:#vi /etc/sysconfig/network-scri ...