题面

给定一棵树,有点权

每次询问给出一些点对,求这些点对之间的路径的并集上不同权值的个数,以及这些权值的$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. admin添加用户时报错:(1452, 'Cannot add or update a child row: a foreign key constraint fails (`mxonline`.`django_admin_l

    在stackoverflow找到答案: DATABASES = { 'default': { ... 'OPTIONS': { "init_command": "SET ...

  2. 分享一个工作中遇得到的sql(按每天每人统计拖车次数与小修次数)

    查询每人每天的数据 首先先建表 CREATE TABLE `user` ( `name` ) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CR ...

  3. AVL重平衡细节——插入

    话说这个系列鸽了好久,之前在准备语言考试,就没管博客了,现在暑假咱们继续上路! 每当我们进行一次插入之后,整棵AVL树的平衡性就有可能发生改变,为了控制整棵树的高度,我们需要通过一系列变换(重平衡)来 ...

  4. java二分法来求一个数组中一个值的key

    package TestArray; import java.util.Arrays; /** * 二分法查找 */ public class Test { public static void ma ...

  5. 一步一步构建手机WebApp开发——页面布局篇

    继上一篇:一步一步构建手机WebApp开发——环境搭建篇过后,我相信很多朋友都想看看实战案例,这一次的教程是页面布局篇,先上图: 如上图所示,此篇教程便是教初学者如何快速布局这样的页面.废话少说,直接 ...

  6. P5056 插头dp

    题面 Source: unordered_map: #include <iostream> #include <tr1/unordered_map> #include < ...

  7. kaldi常用文件查看指令

    目录 1. ark特征文件 2. FST文件 3. mdl模型文件 4. 决策树文件 5. ali.gz对齐文件 资料来自kaldi官方文档. 转载注明出处. 1. ark特征文件 copy-feat ...

  8. BZOJ 1923 SDOI2010 外星千足虫 异或方程组+bitset

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1923 懒得贴题目了......这就是解一个异或方程组的裸题...... YY了一下异或方程 ...

  9. 最短路径——Bellman-Ford算法

    一.相关定义 最短路径:求源点到某特定点的最短距离 特点:Bellman-Ford算法主要是针对有负权值的图,来判断该图中是否有负权回路或者存在最短路径的点 局限性:算法效率不高,不如SPFA算法 时 ...

  10. Mac下使用Charles抓包Android

    原文地址:http://fanjiajia.cn/2018/11/21/Mac%E4%B8%8B%E4%BD%BF%E7%94%A8Charles%E6%8A%93%E5%8C%85Android/ ...