树上莫队共有三种写法:

  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. Redis记录-redis和memcached的区别

    1.Redis和Memcache都是将数据存放在内存中,都是内存数据库.不过memcache还可用于缓存其他东西,例如图片.视频等等: 2.Redis不仅仅支持简单的k/v类型的数据,同时还提供lis ...

  2. SQL记录-PLSQL集合

    PL/SQL集合 集合是一个有序组具有相同的数据类型的元素.每个元素进行标识的唯一标表示其在集合中的位置. PL/SQL提供了三种集合类型: 索引表或关联数组 嵌套表 可变大小的数组或变长数组 Ora ...

  3. bzoj千题计划226:bzoj2763: [JLOI2011]飞行路线

    http://www.lydsy.com/JudgeOnline/problem.php?id=2763 这也算分层图最短路? dp[i][j]到城市i,还剩k次免费次数的最短路 #include&l ...

  4. PHP-PSR-[0-4]代码规范

    PHP-FIG 在说啥是PSR-[0-4]规范的之前,我觉得我们有必要说下它的发明者和规范者:PHP-FIG,它的网站是:www.php-fig.org.就是这个联盟组织发明和创造了PSR-[0-4] ...

  5. 最好用的xshell替代软件----FinalShell工具

    2017年8月份NetSarang公司旗下软件家族的官方版本被爆被植入后门着实让我们常用的Xshell,Xftp等工具火了一把,很长时间都是在用Xshell,不过最近发现了一款同类产品FinalShe ...

  6. ASP.NET记录错误日志的方式

    程序记录错误日志是一种看起来对一般用户没什么作用,但对程序开发者用处很大的东西,它能查出错误或异常的程序马迹.那么,常用的记录错误日志的方式有哪些呢? 大多数情况下使用的是 1.直接记录为txt/xm ...

  7. 浅说Get请求和Post请求

    Web 上最常用的两种 Http 请求就是 Get 请求和 Post 请求了.我们在做 java web 开发时,也总会在 servlet 中通过 doGet 和 doPost 方法来处理请求:更经常 ...

  8. CS229 笔记02

    CS229 笔记02 公式推导 $ {\text {For simplicity, Let }} A, B, C \in {\Bbb {R}}^{n \times n}. $ ​ $ {\bf {\t ...

  9. shell 判断为空打印

    判断参数是否为空-空退出并打印null #!/bin/sh echo $ name=${:?"null"} echo $name

  10. Memcached命令:简单获取缓存value用法

    Memcached:命令用法1.cmd 输入telnet ip  端口 进入memcached服务端窗口比如:xxx.Token_T1435622096xxx为key获取此key的memcached ...