[BZOJ3757]苹果树(树上莫队)
树上莫队共有三种写法:
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]苹果树(树上莫队)的更多相关文章
- 【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)
2016-05-09 UPD:学习了新的DFS序列分块,然后发现这个东西是战术核导弹?反正比下面的树分块不知道要快到哪里去了 #include<cmath> #include<cst ...
- BZOJ.3757.苹果树(树上莫队)
题面链接 /* 代码正确性不保证..(不过交了SPOJ没WA T了最后一个点) 在DFS序做莫队 当一个点不是另一个点的LCA时,需要加上它们LCA的贡献 */ #include <cmath& ...
- 【BZOJ-3757】苹果树 块状树 + 树上莫队
3757: 苹果树 Time Limit: 20 Sec Memory Limit: 256 MBSubmit: 1305 Solved: 503[Submit][Status][Discuss] ...
- BZOJ3757: 苹果树【树上莫队】
Description 神犇家门口种了一棵苹果树.苹果树作为一棵树,当然是呈树状结构,每根树枝连接两个苹果,每个苹果都可以沿着一条由树枝构成的路径连到树根,而且这样的路径只存在一条.由于这棵苹果树 ...
- 2018.09.16 bzoj3757: 苹果树(树上莫队)
传送门 一道树上莫队. 先用跟bzoj1086一样的方法给树分块. 分完之后就可以莫队了. 但是两个询问之间如何转移呢? 感觉很难受啊. 我们定义S(u,v)" role="pre ...
- 【BZOJ3757】苹果树(树上莫队)
点此看题面 大致题意: 每次问你树上两点之间路径中有多少种颜色,每次询问可能会将一种颜色\(a\)看成\(b\). 树上莫队 这题是一道树上莫队板子题. 毕竟求区间中有多少种不同的数是莫队算法的经典应 ...
- 树上莫队 wowow
构建:像线性的莫队那样,依旧是按sqrt(n)为一块分块. int dfs(int x){ ; dfn[x]=++ind; ;i<=;i++) if (bin[i]<=deep[x]) f ...
- [BZOJ 3052] [wc2013] 糖果公园 【树上莫队】
题目链接:BZOJ - 3052 题目分析 这道题就是非常经典的树上莫队了,并且是带修改的莫队. 带修改的莫队:将询问按照 左端点所在的块编号为第一关键字,右端点所在的块为第二关键字,位于第几次修改之 ...
- spoj COT2 - Count on a tree II 树上莫队
题目链接 http://codeforces.com/blog/entry/43230树上莫队从这里学的, 受益匪浅.. #include <iostream> #include < ...
随机推荐
- P3932 浮游大陆的68号岛
P3932 浮游大陆的68号岛 妖精仓库的储物点可以看做在一个数轴上.每一个储物点会有一些东西,同时他们之间存在距离. 每次他们会选出一个小妖精,然后剩下的人找到区间[l,r]储物点的所有东西,清点完 ...
- P2868 [USACO07DEC]观光奶牛Sightseeing Cows
P2868 [USACO07DEC]观光奶牛Sightseeing Cows [](https://www.cnblogs.com/images/cnblogs_com/Tony-Double-Sky ...
- JMS学习(六)--提高非持久订阅者的可靠性 以及 订阅恢复策略
一,非持久订阅者 和 实时消费消息 在这篇文章中区分了Domain为Pub/Sub.Destination为Topic时,消费者有两种:持久订阅者 和 非持久订阅者. 对于持久订阅者而言,只要订阅了某 ...
- javascript公有静态成员
公共静态成员在javascript中并没有特殊语法来表示静态成员.但是可以通过使用构造函数向其添加属性这种方式. //构造函数 var Gadget = function(){}; //静态方法 Ga ...
- ML—R常用多元统计分析包(持续更新中……)
基本的R包已经实现了传统多元统计的很多功能,然而CRNA的许多其它包提供了更深入的多元统计方法,下面要综述的包主要分为以下几个部分: 1) 多元数据可视化(Visualising multivaria ...
- C. NN and the Optical Illusion(几何)
题目链接:http://codeforces.com/contest/1100/problem/C 题目大意:给你n和r,n指的是有n个圆围在里面的圆的外面,r指的是里面的圆的半径,然后让你求外面的圆 ...
- oracle开机自启,开机自动关闭防火墙,开机监听自启
1.修改oratab 2,修改rc.local 3.关闭防火墙,设置开机时清空所有规则 参考文章: 1.https://blog.csdn.net/weeknd/article/details/726 ...
- 如何新建Quartus工程—FPGA入门教程【钛白Logic】
这一章我们来实现第一个FPGA工程—LED流水灯.我们将通过流水灯例程向大家介绍一次完整的FPGA开发流程,从新建工程,代码设计,综合实现,管脚约束,下载FPGA程序.掌握本章内容,大家就算正式的开始 ...
- ZJOI2019爆蛋记
Day-2 玩了一个下午,逛了填海校园,晚上吃肯德基 Day-1 上午听lyx巨佬讲课,讲到一半发现,越听越听不懂... 于是打开电脑开始刷知乎 下午听kcz孔爷讲课,emmmm电脑被我玩没电了... ...
- 常用Javascript集锦【不定期更新】
怎样用javascript删除某个HEML标签 document.getElementById(id).parentNode.removeChild(document.getElementById(i ...