2018.09.16 bzoj3757: 苹果树(树上莫队)
传送门
一道树上莫队。
先用跟bzoj1086一样的方法给树分块。
分完之后就可以莫队了。
但是两个询问之间如何转移呢?
感觉很难受啊。
我们定义S(u,v)" role="presentation" style="position: relative;">S(u,v)S(u,v)表示u->v这条路径的点集,T(u,v)" role="presentation" style="position: relative;">T(u,v)T(u,v)表示S(u,v)" role="presentation" style="position: relative;">S(u,v)S(u,v) xor" role="presentation" style="position: relative;">xorxor lca(u,v)" role="presentation" style="position: relative;">lca(u,v)lca(u,v),同时我们令上一个询问是S(predu,predv)" role="presentation" style="position: relative;">S(predu,predv)S(predu,predv)。
对于T(u,v)" role="presentation" style="position: relative;">T(u,v)T(u,v)有一个恒等式:
T(u,v)=S(root,u)" role="presentation" style="position: relative;">T(u,v)=S(root,u)T(u,v)=S(root,u) xor" role="presentation" style="position: relative;">xorxor S(root,v)" role="presentation" style="position: relative;">S(root,v)S(root,v)
因此有:
T(predu,predv)=S(root,predu)" role="presentation" style="position: relative;">T(predu,predv)=S(root,predu)T(predu,predv)=S(root,predu) xor" role="presentation" style="position: relative;">xorxor S(root,predv)" role="presentation" style="position: relative;">S(root,predv)S(root,predv)
因此有:
T(u,v)" role="presentation" style="position: relative;">T(u,v)T(u,v) xor" role="presentation" style="position: relative;">xorxor T(predu,predv)=S(root,u)" role="presentation" style="position: relative;">T(predu,predv)=S(root,u)T(predu,predv)=S(root,u) xor" role="presentation" style="position: relative;">xorxor S(root,v)" role="presentation" style="position: relative;">S(root,v)S(root,v) xor" role="presentation" style="position: relative;">xorxor S(root,predu)" role="presentation" style="position: relative;">S(root,predu)S(root,predu) xor" role="presentation" style="position: relative;">xorxor S(root,predv)" role="presentation" style="position: relative;">S(root,predv)S(root,predv)
因此有:
T(u,v)=T(predu,predv)" role="presentation" style="position: relative;">T(u,v)=T(predu,predv)T(u,v)=T(predu,predv) xor" role="presentation" style="position: relative;">xorxor T(predu,v)" role="presentation" style="position: relative;">T(predu,v)T(predu,v) xor" role="presentation" style="position: relative;">xorxor T(u,predv)" role="presentation" style="position: relative;">T(u,predv)T(u,predv)
那么更新就比较容易了。
代码:
#include<bits/stdc++.h>
#define N 100005
#define sig 24
using namespace std;
int n,m,rt,sum,ans[N],blo[N],dfn[N],dep[N],first[N],cnt,blos,top,fa[N][sig],mul[N],block,tot,stk[N],tim[N],col[N];
bool vis[N];
struct edge{int v,next;}e[N<<1];
struct Q{int u,v,a,b,id;}q[N];
inline bool cmp(Q a,Q b){return blo[a.u]==blo[b.u]?dfn[a.v]<dfn[b.v]:blo[a.u]<blo[b.u];}
inline void add(int u,int v){e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;}
inline void dfs(int p){
dfn[p]=++tot,dep[p]=dep[fa[p][0]]+1;
int tmp=top;
for(int i=1;i<sig;++i)
if(dep[p]<mul[i])break;
else fa[p][i]=fa[fa[p][i-1]][i-1];
for(int i=first[p];i;i=e[i].next){
int v=e[i].v;
if(v==fa[p][0])continue;
fa[v][0]=p,dfs(v);
if(top-tmp>=block){
++blos;
while(top!=tmp)blo[stk[top--]]=blos;
}
}
stk[++top]=p;
}
inline int lca(int x,int y){
if(dep[x]<dep[y])x^=y,y^=x,x^=y;
int tmp=dep[x]-dep[y];
for(int i=0;i<sig;++i)if(tmp&(1<<i))x=fa[x][i];
if(x==y)return x;
for(int i=sig-1;~i;--i)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
inline void update(int x){
if(vis[x]){
vis[x]=0,--tim[col[x]];
if(tim[col[x]]==0)--sum;
}
else{
vis[x]=1,++tim[col[x]];
if(tim[col[x]]==1)++sum;
}
}
inline void reverse(int x,int y){
while(x!=y){
if(dep[x]<dep[y])x^=y,y^=x,x^=y;
update(x),x=fa[x][0];
}
}
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
int main(){
n=read(),m=read(),mul[0]=1,block=sqrt(n);
for(int i=1;i<=n;++i)col[i]=read();
for(int i=1;i<=n;++i){
int u=read(),v=read();
if(!u||!v)rt=u+v;
else add(u,v),add(v,u);
}
for(int i=1;i<sig;++i)mul[i]=mul[i-1]<<1;
dfs(rt),++blos;
while(top)blo[stk[top--]]=blos;
for(int i=1;i<=m;++i){
q[i].u=read(),q[i].v=read(),q[i].a=read(),q[i].b=read(),q[i].id=i;
if(dfn[q[i].u]>dfn[q[i].v])q[i].u^=q[i].v,q[i].v^=q[i].u,q[i].u^=q[i].v;
}
sort(q+1,q+m+1,cmp);
int Lca=lca(q[1].u,q[1].v);
reverse(q[1].u,q[1].v),update(Lca),ans[q[1].id]=sum;
if(q[1].a!=q[1].b&&tim[q[1].a]&&tim[q[1].b])--ans[q[1].id];
for(int i=2;i<=m;++i){
update(Lca),reverse(q[i-1].u,q[i].u),reverse(q[i-1].v,q[i].v);
Lca=lca(q[i].u,q[i].v),update(Lca),ans[q[i].id]=sum;
if(q[i].a!=q[i].b&&tim[q[i].a]&&tim[q[i].b])--ans[q[i].id];
}
for(int i=1;i<=m;++i)printf("%d\n",ans[i]);
return 0;
}
2018.09.16 bzoj3757: 苹果树(树上莫队)的更多相关文章
- [BZOJ3757]苹果树(树上莫队)
树上莫队共有三种写法: 1.按DFS序列分块,和普通莫队类似.常数大,不会被卡. 2.按块状树的方式分块.常数小,会被菊花图卡到O(n). 3.按[BZOJ1086]王室联邦的方式分块.常数小,不会被 ...
- 【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 神犇家门口种了一棵苹果树.苹果树作为一棵树,当然是呈树状结构,每根树枝连接两个苹果,每个苹果都可以沿着一条由树枝构成的路径连到树根,而且这样的路径只存在一条.由于这棵苹果树 ...
- 【BZOJ3757】苹果树(树上莫队)
点此看题面 大致题意: 每次问你树上两点之间路径中有多少种颜色,每次询问可能会将一种颜色\(a\)看成\(b\). 树上莫队 这题是一道树上莫队板子题. 毕竟求区间中有多少种不同的数是莫队算法的经典应 ...
- 树上莫队 wowow
构建:像线性的莫队那样,依旧是按sqrt(n)为一块分块. int dfs(int x){ ; dfn[x]=++ind; ;i<=;i++) if (bin[i]<=deep[x]) f ...
- 【BZOJ4129】Haruna’s Breakfast(树上莫队)
[BZOJ4129]Haruna's Breakfast(树上莫队) 题面 BZOJ Description Haruna每天都会给提督做早餐! 这天她发现早饭的食材被调皮的 Shimakaze放到了 ...
- 【SPOJ】Count On A Tree II(树上莫队)
[SPOJ]Count On A Tree II(树上莫队) 题面 洛谷 Vjudge 洛谷上有翻译啦 题解 如果不在树上就是一个很裸很裸的莫队 现在在树上,就是一个很裸很裸的树上莫队啦. #incl ...
随机推荐
- REST 服务器调试 RESTDebugger.exe 和浏览器测试
开发一个简单的rest服务器, 增加了一些函数,比如返回系统当前时间 如何验证是否正确呢,不需要自己编写客户端调用程序了, 可以直接使用RESTDebugger.exe D:\Program File ...
- jsp页面转发获取不到参数
使用的是<input type="hidden" name="nameid" value="${nameid}"/>,隐藏默认值 ...
- Spring 集成Hibernate的三种方式
首先把hibernate的配置文件hibernate.cfg.xml放入spring的src目录下,并且为了便于测试导入了一个实体类Student.java以及它的Student.hbm.xml文件 ...
- Python递归的经典案例
目录 : 一.递归的简介 二.递归的经典应用 2.1 递归求阶乘 2.2 递归推斐波那契数列 2.3 二分法找有序列表指定值 2.4 递归解汉诺塔 前言: 当我们碰到诸如需要求阶乘或斐 ...
- python yield 浅析-转载
如何生成斐波那契數列 斐波那契(Fibonacci)數列是一个非常简单的递归数列,除第一个和第二个数外,任意一个数都可由前两个数相加得到.用计算机程序输出斐波那契數列的前 N 个数是一个非常简单的问题 ...
- ContextLoaderListener和Spring MVC中的DispatcherServlet学习
DispatcherServlet介绍 DispatcherServlet是Spring前端控制器的实现,提供Spring Web MVC的集中访问点,并且负责职责的分派,与Spring IoC容器无 ...
- 在winsshd 中添加id_rsa.pub 实现Windows 服务器主机自动信任Linux 客户端
文章一. 生成密钥: 在Linux主机(ssh客户端),通过ssh-keygen在建立SSH keys# ssh-keygen -t rsa (连续三次回车,即在本地生成了公钥和私钥,不设置密码)将在 ...
- python简单基础代码
1.从键盘输入两个数,并计算A的B次幂:number1=raw_input('input number1:')number2=raw_input('input number2:')print 'num ...
- zoj1109-Language of FatMouse 【字典树】
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=109 Language of FatMouse Time Limit: 10 S ...
- 122. Best Time to Buy and Sell Stock II (Array;Greedy)
Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...