种树 by yoyoball [树分块+bitset]
题面
给定一棵树,有点权
每次询问给出一些点对,求这些点对之间的路径的并集上不同权值的个数,以及这些权值的$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]的更多相关文章
- 洛谷 P6177 - Count on a tree II/【模板】树分块(树分块)
洛谷题面传送门 好家伙,在做这道题之前我甚至不知道有个东西叫树分块 树分块,说白了就是像对序列分块一样设一个阈值 \(B\),然后在树上随机撒 \(\dfrac{n}{B}\) 个关键点,满足任意一个 ...
- 【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)
2016-05-09 UPD:学习了新的DFS序列分块,然后发现这个东西是战术核导弹?反正比下面的树分块不知道要快到哪里去了 #include<cmath> #include<cst ...
- 2015北京网络赛 J Clarke and puzzle 求五维偏序 分块+bitset
Clarke and puzzle Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://hihocoder.com/contest/acmicpc20 ...
- [BZOJ 1086] [SCOI2005] 王室联邦 【树分块】
题目链接:BZOJ - 1086 题目分析 这道题要求给树分块,使得每一块的大小在 [B, 3B] 之间,并且可以通过一个块外的节点(块根)使得整个块联通. 那么我们使用一种 DFS,维护一个栈,DF ...
- hihocoder1236(北京网络赛J):scores 分块+bitset
北京网络赛的题- -.当时没思路,听大神们说是分块+bitset,想了一下发现确实可做,就试了一下,T了好多次终于过了 题意: 初始有n个人,每个人有五种能力值,现在有q个查询,每次查询给五个数代表查 ...
- 洛谷.2590.[ZJOI2008]树的统计(树分块)
题目链接 Update:这种分块写法...可以被卡掉啊... 好像没有靠谱的树分块写法... /* 对树上节点进行分块,每个点记录dep,fa,val,Max,Sum,Max,Sum表示当前点在该块内 ...
- BZOJ.3720.Gty的妹子树(树分块)
题目链接 洛谷上惨遭爆零是为什么.. 另外这个树分块算法是假的. /* 插入删除只涉及一个数,故每次可以枚举一遍,而不是重构完后sort */ #include<cmath> #inclu ...
- 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 ...
- 【bzoj2741】[FOTILE模拟赛]L 可持久化Trie树+分块
题目描述 FOTILE得到了一个长为N的序列A,为了拯救地球,他希望知道某些区间内的最大的连续XOR和. 即对于一个询问,你需要求出max(Ai xor Ai+1 xor Ai+2 ... xor A ...
随机推荐
- java的动态验证码单线设计
1.java的动态验证码我这里将介绍两种方法: 一:根据java本身提供的一种验证码的写法,这种呢只限于大家了解就可以了,因为java自带的模式编写的在实际开发中是没有意义的,所以只供学习一下就可以了 ...
- python面向对象-cs游戏示例
#!/usr/local/bin/python3 # -*- coding:utf-8 -*- class Role(object): n = 123 # 类变量 name = "我是类na ...
- 爬虫之requests模块基础
一.request模块介绍 1. 什么是request模块 - python中原生的基于网络请求的模块,模拟浏览器发起请求. 2. 为什么使用request模块 - urllib需要手动处理url编码 ...
- ecshop漏洞修复 以及如何加固ecshop网站安全?
由于8月份的ECSHOP通杀漏洞被国内安全厂商爆出后,众多使用ecshop程序源码的用户大面积的受到了网站被篡改,最明显的就是外贸站点被跳转到一些仿冒的网站上去,导致在谷歌的用户订单量迅速下降,从百度 ...
- Waterline从概念到实操
Waterline基本介绍 Waterline是什么 Waterline是下一代存储和检索引擎,也是Sails框架中使用的默认ORM . ORM的基本概念 Object Relational Mapp ...
- python2.7练习小例子(二十五)
25):题目:有5个人坐在一起,问第五个人多少岁?他说比第4个人大2岁.问第4个人岁数,他说比第3个人大2岁.问第三个人,又说比第2人大两岁.问第2个人,说比第一个人大两岁.最后问第一个人,他 ...
- IDEA常用操作(一)
1.视图的调整 左下右的侧边栏如何关闭?——右击选择remove from sidebar 面板上(左下右)的导航栏视图如何隐藏——可以在左下角悬停显示,单击隐藏/开启侧边栏 想打开其它视图怎么办?— ...
- Altium Designer -- 精心总结
如需转载请注明出处:http://blog.csdn.NET/qq_29350001/article/details/52199356 以前是使用DXP2004来画图的,后来转行.想来已经有一年半的时 ...
- Hibernate-ORM:16.Hibernate中的二级缓存Ehcache的配置
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 本篇博客讲述Hibernate中的二级缓存的配置,作者将使用的是ehcache缓存 一,目录 1.二级缓存的具 ...
- 激活Windows Server 2008R2
1. 用管理员身份运行mini-KMS_Activator_v1.053_ENG 2. 点击倒数第二个菜单Activation Windows VL 选择数字1 下一步选择Y 不管后面报不报错 3. ...