树上莫队共有三种写法:

  1.按DFS序列分块,和普通莫队类似。常数大,不会被卡。

  2.按块状树的方式分块。常数小,会被菊花图卡到O(n)。

  3.按[BZOJ1086]王室联邦的方式分块。常数小,不会被卡。唯一的缺点是较抽象,一个块可能是不连通的。

权衡一下当然还是写第三种做法,具体看代码。

然后还有一个问题,手动模拟莫队移动左右端点指针的过程,会发现LCA处较难处理,它常常是跟其它点反着的。于是我们每次移指针的时候都忽略LCA,最后询问的时候加上LCA求解答案再减去LCA。再模拟会发现,所有方案都可以处理了。

以及要注意每个询问如果左端点所在块编号比右端点所在块大则需要交换左右端点。询问的排序方式是:若两端点不在同一块则按块编号排序,否则按DFS序排序。也就是按(bel[i],dfn[i])的双关键字排序。

 #include<cmath>
#include<cstdio>
#include<algorithm>
#define rep(i,l,r) for (int i=(l); i<=(r); i++)
#define For(i,x) for (int i=h[x],k; i; i=nxt[i])
using namespace std; const int N=;
int n,m,B,u,v,tim,top,tot,a[N],stk[N],b[N],dep[N],fa[N][];
int cnt,res,rt,vis[N],ans[N],dfn[N],s[N],h[N],to[N],nxt[N];
struct P{ int l,r,x,y,id; }q[N]; bool cmp(const P &x,const P &y){ return b[x.l]==b[y.l] ? dfn[x.r]<dfn[y.r] : b[x.l]<b[y.l]; }
void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; } void dfs(int x){
dfn[x]=++tim; int tmp=top;
rep(i,,) fa[x][i]=fa[fa[x][i-]][i-];
For(i,x) if ((k=to[i])!=fa[x][]){
fa[k][]=x; dep[k]=dep[x]+; dfs(k);
if (top-tmp>=B){ ++tot; while (top!=tmp) b[stk[top--]]=tot; }
}
stk[++top]=x;
} int lca(int x,int y){
if (dep[x]<dep[y]) swap(x,y);
int t=dep[x]-dep[y];
for (int i=; ~i; i--) if (t&(<<i)) x=fa[x][i];
if (x==y) return x;
for (int i=; ~i; i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][];
} void upd(int x){
if (vis[x]){ s[a[x]]--; if (!s[a[x]]) res--; }
else { s[a[x]]++; if (s[a[x]]==) res++; }
vis[x]^=;
} void work(int x,int y){
for (; x!=y; upd(x),x=fa[x][])
if (dep[x]<dep[y]) swap(x,y);
} int main(){
freopen("bzoj3757.in","r",stdin);
freopen("bzoj3757.out","w",stdout);
scanf("%d%d",&n,&m); B=sqrt(n);
rep(i,,n) scanf("%d",&a[i]);
rep(i,,n){
scanf("%d%d",&u,&v);
if (!u || !v) { rt=u+v; continue; }
add(u,v); add(v,u);
}
dfs(rt);
while (top) b[stk[top--]]=tot;
rep(i,,m){
scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].x,&q[i].y); q[i].id=i;
if (b[q[i].l]>b[q[i].r]) swap(q[i].l,q[i].r);
}
sort(q+,q+m+,cmp);
int L=rt,R=rt;
rep(i,,m){
work(L,q[i].l); work(R,q[i].r); L=q[i].l; R=q[i].r;
int f=lca(L,R); upd(f);
ans[q[i].id]=res-(int)(q[i].x!=q[i].y&&s[q[i].x]&&s[q[i].y]); upd(f);
}
rep(i,,m) printf("%d\n",ans[i]);
return ;
}

[BZOJ3757]苹果树(树上莫队)的更多相关文章

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

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

  2. BZOJ.3757.苹果树(树上莫队)

    题面链接 /* 代码正确性不保证..(不过交了SPOJ没WA T了最后一个点) 在DFS序做莫队 当一个点不是另一个点的LCA时,需要加上它们LCA的贡献 */ #include <cmath& ...

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

    3757: 苹果树 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 1305  Solved: 503[Submit][Status][Discuss] ...

  4. BZOJ3757: 苹果树【树上莫队】

    Description ​ 神犇家门口种了一棵苹果树.苹果树作为一棵树,当然是呈树状结构,每根树枝连接两个苹果,每个苹果都可以沿着一条由树枝构成的路径连到树根,而且这样的路径只存在一条.由于这棵苹果树 ...

  5. 2018.09.16 bzoj3757: 苹果树(树上莫队)

    传送门 一道树上莫队. 先用跟bzoj1086一样的方法给树分块. 分完之后就可以莫队了. 但是两个询问之间如何转移呢? 感觉很难受啊. 我们定义S(u,v)" role="pre ...

  6. 【BZOJ3757】苹果树(树上莫队)

    点此看题面 大致题意: 每次问你树上两点之间路径中有多少种颜色,每次询问可能会将一种颜色\(a\)看成\(b\). 树上莫队 这题是一道树上莫队板子题. 毕竟求区间中有多少种不同的数是莫队算法的经典应 ...

  7. 树上莫队 wowow

    构建:像线性的莫队那样,依旧是按sqrt(n)为一块分块. int dfs(int x){ ; dfn[x]=++ind; ;i<=;i++) if (bin[i]<=deep[x]) f ...

  8. [BZOJ 3052] [wc2013] 糖果公园 【树上莫队】

    题目链接:BZOJ - 3052 题目分析 这道题就是非常经典的树上莫队了,并且是带修改的莫队. 带修改的莫队:将询问按照 左端点所在的块编号为第一关键字,右端点所在的块为第二关键字,位于第几次修改之 ...

  9. spoj COT2 - Count on a tree II 树上莫队

    题目链接 http://codeforces.com/blog/entry/43230树上莫队从这里学的,  受益匪浅.. #include <iostream> #include < ...

随机推荐

  1. Hadoop生态圈-Azkaban实现文件上传到hdfs并执行MR数据清洗

    Hadoop生态圈-Azkaban实现文件上传到hdfs并执行MR数据清洗 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 如果你没有Hadoop集群的话也没有关系,我这里给出当时我 ...

  2. SQL记录-PLSQL日期与时间

    PL/SQL日期及时间 PL/SQL提供两个日期和时间相关的数据类型: 日期时间(Datetime)数据类型 间隔数据类型 datetime数据类型有: DATE TIMESTAMP TIMESTAM ...

  3. lua元表详解

    元表的作用 元表是用来定义对table或userdata操作方式的表 举个例子 local t1 = {1} local t2 = {2} local t3 = t1 + t2 我们直接对两个tabl ...

  4. [转载]嵌入式C语言中的Doxygen注释模板

    http://blog.csdn.net/willerency/article/details/7083953 嵌入式C语言开发中通常使用Doxygen进行文档的生成.Doxygen支持多种格式,非常 ...

  5. 【NOI】2017 整数(BZOJ 4942,LOJ2302) 压位+线段树

    [题目]#2302. 「NOI2017」整数 [题意]有一个整数x,一开始为0.n次操作,加上a*2^b,或询问2^k位是0或1.\(n \leq 10^6,|a| \leq 10^9,0 \leq ...

  6. oracel 复制A列的内容到列

    update jieguo1 t set t.chinesetablename =t.tablezhushi where length(t.chinesetablename) >= 15 and ...

  7. curl wget 不验证证书进行https请求【转】

    $ wget 'https://x.x.x.x/get_ips' --no-check-certificate $ curl 'https://x.x.x.x/get_ips' -k 转自 curl ...

  8. jstack查看Java堆栈信息

    命令 jps 查看进程id jstack 1234 查看该进程的线程堆栈信息 对于每个线程,都有如下信息: 线程名,如“main”线程属性(如果是Daemon线程,会有Daemon标识,否则,什么都没 ...

  9. docker 要点学习

    本文主要记录学习和使用docker时遇到的一些问题和踩过的坑 1.本地docker新建redis容器,映射6379端口到本地,本机的java项目再去连,会一直连不上,原因是redis容器中映射端口时需 ...

  10. express-partials使用方法

    1.安装express-partials 方法一:运行cmd用npm install express-partials 方法二:在package.json里面的dependencies添加" ...