bzoj 3757 苹果树(树上莫队算法)
【题意】
有若干个询问,询问路径u,v上的颜色总数,另外有要求a,b,意为将a颜色看作b颜色。
【思路】
vfk真是神系列233。
Quote:
用S(v, u)代表 v到u的路径上的结点的集合。
用root来代表根结点,用lca(v, u)来代表v、u的最近公共祖先。
那么
S(v, u) = S(root, v) xor S(root, u) xor lca(v, u)
其中xor是集合的对称差。
简单来说就是节点出现两次消掉。
lca很讨厌,于是再定义
T(v, u) = S(root, v) xor S(root, u)
观察将curV移动到targetV前后T(curV, curU)变化:
T(curV, curU) = S(root, curV) xor S(root, curU)
T(targetV, curU) = S(root, targetV) xor S(root, curU)
取对称差:
T(curV, curU) xor T(targetV, curU)= (S(root, curV) xor S(root, curU)) xor (S(root, targetV) xor S(root, curU))
由于对称差的交换律、结合律:
T(curV, curU) xor T(targetV, curU)= S(root, curV) xor S(root, targetV)
两边同时xor T(curV, curU):
T(targetV, curU)= T(curV, curU) xor S(root, curV) xor S(root, targetV)
发现最后两项很爽……哇哈哈
T(targetV, curU)= T(curV, curU) xor T(curV, targetV)
(有公式恐惧症的不要走啊 T_T)
也就是说,更新的时候,xor T(curV, targetV)就行了。
即,对curV到targetV路径(除开lca(curV, targetV))上的结点,将它们的存在性取反即可。
from vfleaking
设目前指针处于a,b,且now为已经得到的T(curV,curU)的统计答案,此次询问为u,v,则我们使a->u,b->v,设计一个vis标记,路上取反标记并更新now,即xor T(curV,targetV),最后还要取反lca(u,v)才是一个完整的u->v路径。
【代码】
#include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; typedef long long ll;
const int N = 4e5+;
const int D = ; ll read() {
char c=getchar();
ll f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} struct Edge {
int v,nxt;
}e[N];
int en=,front[N];
void adde(int u,int v)
{
e[++en]=(Edge){v,front[u]}; front[u]=en;
} int n,m,B,B_cnt,now,dfsc,dfn[N],ans[N];
int pos[N],a[N],cnt[N],vis[N],fa[N][D],dep[N],st[N],top; struct Node
{
int id,l,r,a,b;
bool operator < (const Node& rhs) const
{
return pos[l]<pos[rhs.l] || (pos[l]==pos[rhs.l]&&dfn[r]<dfn[rhs.r]);
}
} q[N]; int dfs(int u)
{
FOR(i,,D-)
fa[u][i]=fa[fa[u][i-]][i-];
int size=;
dfn[u]=++dfsc;
trav(u,i)
{
int v=e[i].v;
if(v!=fa[u][]) {
fa[v][]=u;
dep[v]=dep[u]+;
size+=dfs(v);
if(size>=B) {
B_cnt++;
while(size--)
pos[st[top--]]=B_cnt;
}
}
}
st[++top]=u;
return size+;
}
int lca(int u,int v)
{
if(dep[u]<dep[v]) swap(u,v);
int t=dep[u]-dep[v];
FOR(i,,D-)
if((<<i)&t) u=fa[u][i];
if(u==v) return u;
for(int i=D-;i>=;i--)
if(fa[u][i]!=fa[v][i])
u=fa[u][i],v=fa[v][i];
return fa[u][];
}
void upd(int u)
{
if(!vis[u]) {
vis[u]=;
now+=(++cnt[a[u]])==;
} else {
vis[u]=;
now-=(--cnt[a[u]])==;
}
}
void work(int u,int v)
{
while(u!=v)
{
if(dep[u]<dep[v]) swap(u,v);
upd(u); u=fa[u][];
}
}
int main()
{
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
n=read(),m=read();
B=sqrt(n);
FOR(i,,n) a[i]=read();
int rt,u,v;
FOR(i,,n) {
u=read(),v=read();
if(!u) rt=v;
else if(!v) rt=u;
else adde(u,v),adde(v,u);
}
dfs(rt);
B_cnt++;
while(top) pos[st[top--]]=B_cnt;
FOR(i,,m) {
q[i].l=read(),q[i].r=read();
q[i].a=read(),q[i].b=read();
q[i].id=i;
if(dfn[q[i].l]>dfn[q[i].r]) swap(q[i].l,q[i].r);
}
sort(q+,q+m+); work(q[].l,q[].r);
int lc=lca(q[].l,q[].r);
upd(lc);
ans[q[].id]=now;
ans[q[].id]-=(q[].a!=q[].b)&&(cnt[q[].a]&&cnt[q[].b]);
upd(lc); FOR(i,,m) {
work(q[i-].l,q[i].l);
work(q[i-].r,q[i].r);
lc=lca(q[i].l,q[i].r);
upd(lc);
ans[q[i].id]=now;
ans[q[i].id]-=(q[i].a!=q[i].b)&&(cnt[q[i].a]&&cnt[q[i].b]);
upd(lc);
} FOR(i,,m)
printf("%d\n",ans[i]);
return ;
}
bzoj 3757 苹果树(树上莫队算法)的更多相关文章
- BZOJ.3757.苹果树(树上莫队)
题面链接 /* 代码正确性不保证..(不过交了SPOJ没WA T了最后一个点) 在DFS序做莫队 当一个点不是另一个点的LCA时,需要加上它们LCA的贡献 */ #include <cmath& ...
- 【BZOJ 3735】苹果树 树上莫队(树分块+离线莫队+鬼畜的压行)
2016-05-09 UPD:学习了新的DFS序列分块,然后发现这个东西是战术核导弹?反正比下面的树分块不知道要快到哪里去了 #include<cmath> #include<cst ...
- SPOJ COT2 Count on a tree II 树上莫队算法
题意: 给出一棵\(n(n \leq 4 \times 10^4)\)个节点的树,每个节点上有个权值,和\(m(m \leq 10^5)\)个询问. 每次询问路径\(u \to v\)上有多少个权值不 ...
- [BZOJ3757]苹果树(树上莫队)
树上莫队共有三种写法: 1.按DFS序列分块,和普通莫队类似.常数大,不会被卡. 2.按块状树的方式分块.常数小,会被菊花图卡到O(n). 3.按[BZOJ1086]王室联邦的方式分块.常数小,不会被 ...
- BZOJ 3339: Rmq Problem 莫队算法
3339: Rmq Problem 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=3339 Description n个数,m次询问l,r ...
- 【BZOJ】4358: permu 莫队算法
[题意]给定长度为n的排列,m次询问区间[L,R]的最长连续值域.n<=50000. [算法]莫队算法 [题解]考虑莫队维护增加一个数的信息:设up[x]表示数值x往上延伸的最大长度,down[ ...
- uoj #58. 【WC2013】糖果公园(树上莫队算法+修改操作)
[题目链接] http://uoj.ac/problem/58 [题意] 有一棵树,结点有自己的颜色,若干询问:u,v路径上的获益,并提供修改颜色的操作. 其中获益定义为Vc*W1+Vc*W2+…+V ...
- 「日常训练&知识学习」莫队算法(二):树上莫队(Count on a tree II,SPOJ COT2)
题意与分析 题意是这样的,给定一颗节点有权值的树,然后给若干个询问,每次询问让你找出一条链上有多少个不同权值. 写这题之前要参看我的三个blog:Codeforces Round #326 Div. ...
- BZOJ 3757 苹果树 ——莫队算法
挺好的一道题目,怎么就没有版权了呢?大数据拍过了,精神AC.... 发现几种颜色这性质比较垃圾,不可加,莫队硬上. %了一发popoqqq大神的博客, 看了一波VFK关于糖果公园的博客, 又找了wjm ...
随机推荐
- c语言中argc和argv是什么意思?
argc是参数个数,定义为intargv是字符串数组,存的是参数,定义为char**或者char* argv[]比如你编译好的程序为my.exe在命令行执行 my.exe 1 2 3那argc就是4, ...
- 重新格式化hdfs系统的方法
重新格式化hdfs系统的方法: (1)查看hdfs-ste.xml <span style="font-size:18px;"><property> < ...
- Case 架构的实际应用-1
We use testlink to manage cases, and the frame is below: Project Name -All Features(Modules) -Featur ...
- Asp.net Json 解析 与 直接用ip访问返回josn
数据分析 目前手头上需要制作一个天气预报功能,现成的接口已经有了.我随便输入一个城市,然后出现了如下的信息: {"wdata":{"cityName":&quo ...
- Ubuntu对FireFox安装flash插件
有时候我们需要在Ubuntu下采用手动安装一些软件,比如Firefox的Flash插件.Adobe® Flash® Player 是一款轻量级浏览器插件,具有丰富的 Internet 应用运行时间,提 ...
- 第六篇 ORACLE EBS用户界面通用元素或功能背后的道理解析
本篇打算介绍一下ORACLE EBS用户界面(User Interface)中通用的元素或功能背后蕴含的一些道理.这些通用元素或功能包括: List of Values (LOV),值列表 Flexf ...
- linux 防火墙打开端口/屏蔽IP等
开启/禁用 sudo ufw allow|deny [service] 打开或关闭某个端口,例如: sudo ufw allow smtp 允许所有的外部IP访问本机的25/tcp (smtp)端口 ...
- leetcode:Multiply Strings
Given two numbers represented as strings, return multiplication of the numbers as a string. Note: Th ...
- javascript高级编程运用
一//各种尺寸 (size) s += “\r\n网页可见区域宽:“+ document.body.clientWidth; s += “\r\n网页可见区域高:“+ document.body.cl ...
- 初识EasyUI
1.下载Jquery_EasyUI文档,将里面的spket-1.6.18.jar复制放到适合的位置(随意,不要有中文路径).使用命令行将其安装: 进入到文件目录下: 弹出安装界面选择下一步: 选 ...