题目链接:糖果公园

  听说这是一道树上莫队的入门题,于是我就去写了……顺便复习了一下莫队的各种姿势。

  首先,我们要在树上使用莫队,那么就需要像序列一样给树分块。这个分块的过程就是王室联邦这道题(vfleaking大神的博客里也有讲),当然也可以按照\(dfs\)序什么的进行分块。

  但我还是想在这里讲一下我的分块做法(第一种)。我们可以先设一个块的大小$S$,然后对整棵树进行$dfs$。每次我们$dfs$完一棵子树回溯时,我们就把这个点$u$加入到一个队列中,更新$fa_u$的$siz$。这里$siz_u$记录的是以$u$为根的子树中为分好块的节点数。当我们发现$siz_u$超过了$S$时,我们就可以给这些节点新建一个块。最后还会剩下不超过$S$个节点,我们可以新建一个块,也可以把这些点丢到最后新建的那个块中。如果采用后一种方式,那么就保证了每个块的大小都在$[S,3S)$之间且最多只有一个块的大小会大于$2S$。于是我们就得到了一种优美的分块方法。(如果还不懂的话可以去看代码)

  然后,这道题带了修改(其实并没有什么不同,只是需要修改块的大小以及多一个时间流逝的操作),于是给每个操作多一个时间戳即可。树上莫队和序列莫队最大的不同就在于如何转移。也就是我们如何由路径$(u_i,v_j)$走到路径$(u_j,v_j)$上去。其实就是先把$u_i$走到$u_j$,再把$v_i$走到$v_j$即可。注意,这里为了方便考虑,上述路径均没有把深度最小的点给算进去。这里没有讲清楚……还是往后看吧……

  至于证明吗……我们先设几个东西(下列内容参考vfleaking大神的博客)……

  设$S(u,v)$表示路径$(u,v)$上所有点的集合,$T(u,v)$表示$S(u,v)$去掉$lca(u,v)$之后剩下的点集。那么显然有:$$T(u,v)=S(root,u) \  xor \  S(root,v)$$

  这里的$xor$指的是集合的对称差。简单来说就是把出现偶数次的节点给删掉。这个操作显然和异或差不多,性质也差不多。

  于是我们可以考虑一下从$T(u_i,v_i)$转移到$T(u_j,v_j)$需要改变一些什么。$$\because T(u_i,v_i)=S(root,u_i)\ xor \ S(root,v_i)\quad T(u_j,v_j)=S(root,u_j)\ xor \ S(root,v_j)$$ $$\therefore T(u_i,v_i)\ xor \ T(u_j,v_j)=T(u_i,u_j)\ xor \ T(v_i,v_j)$$ $$\therefore T(u_j,v_j)=T(u_i,v_i)\ xor \ T(u_i,u_j)\ xor \ T(v_i,v_j)$$

  于是我们从$T(u_i,v_i)$转移到$T(u_j,v_j)$只需要把点集$T(u_i,u_j)$和$T(v_i,v_j)$中的点存在性全部取反即可。

  至于如何$O(1)$地进行插入和删除就不需要我多说了吧……

  其实我感觉有vfleaking大神的博客应该不需要我的这一篇才对

  下面贴代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 100010 using namespace std;
typedef long long llg; int n,m,q,V[maxn],co[maxn],num[maxn];
int fa[maxn][17],dep[maxn],siz[maxn];
int head[maxn],next[maxn<<1],to[maxn<<1],tt;
int qt[maxn],fr[maxn],qto,nblo,sizblo;
llg sw[maxn],now,ans[maxn]; bool vis[maxn];
struct data{
int u,v,t;
bool operator < (const data &h)const{
if(fr[u]!=fr[h.u]) return fr[u]<fr[h.u];
if(fr[v]!=fr[h.v]) return fr[v]<fr[h.v];
return t<h.t;
}
}s[maxn],cha[maxn<<1]; int getint(){
int w=0;bool q=0;
char c=getchar();
while((c>'9'||c<'0')&&c!='-') c=getchar();
if(c=='-') c=getchar(),q=1;
while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
return q?-w:w;
} void link(int x,int y){
to[++tt]=y;next[tt]=head[x];head[x]=tt;
to[++tt]=x;next[tt]=head[y];head[y]=tt;
} void dfs(int u,int ff){
qt[++qto]=u;
fa[u][0]=ff; dep[u]=dep[ff]+1;
for(int i=1,now=2;now<dep[u];i++,now<<=1)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=head[u],v;v=to[i],i;i=next[i])
if(v!=ff){
dfs(v,u); siz[u]+=siz[v];
if(siz[u]>=sizblo){
nblo++; siz[u]=0;
while(qt[qto]!=u) fr[qt[qto--]]=nblo;
}
}
siz[u]++;
} void change(int u){
now-=V[co[u]]*sw[num[co[u]]];
if(vis[u]) num[co[u]]--,vis[u]=0;
else num[co[u]]++,vis[u]=1;
now+=V[co[u]]*sw[num[co[u]]];
} void timego(int x){
if(!cha[x].t) return;
bool ww=vis[cha[x].t];
if(ww) change(cha[x].t);
co[cha[x].t]=cha[x].v;
if(ww) change(cha[x].t);
} int lca(int u,int v){
if(dep[u]<dep[v]) swap(u,v); int t=0;
for(int now=1;now<dep[u];now<<=1) t++;t--;
for(int i=t;i>=0;i--)
if(dep[fa[u][i]]>=dep[v]) u=fa[u][i];
if(u==v) return u;
for(int i=t;i>=0;i--)
if(fa[u][i]!=fa[v][i])
u=fa[u][i],v=fa[v][i];
return fa[u][0];
} void query(int u,int v){
int g=lca(u,v);
while(u!=g) change(u),u=fa[u][0];
while(v!=g) change(v),v=fa[v][0];
} int main(){
File("a");
n=getint(); m=getint(); q=getint();
for(int i=1;i<=m;i++) V[i]=getint();
for(int i=1;i<=n;i++) sw[i]=sw[i-1]+getint();
for(int i=1;i<n;i++) link(getint(),getint());
sizblo=pow(n,2.0/3.0)+1; dfs(1,0); tt=0;
for(int i=1;i<=n;i++) if(!fr[i]) fr[i]=nblo;
for(int i=1;i<=n;i++) co[i]=num[i]=getint();
for(int i=1,ty;i<=q;i++){
ty=getint(); s[i].t=++tt;
s[i].u=getint(); s[i].v=getint();
if(!ty){
cha[i].u=num[s[i].u]; cha[i].t=s[i].u;
cha[i].v=num[s[i].u]=s[i].v;
cha[i+q]=cha[i]; swap(cha[i+q].u,cha[i+q].v);
}
else if(fr[s[i].u]>fr[s[i].v]) swap(s[i].u,s[i].v);
}
for(int i=1;i<=n;i++) num[i]=0;
sort(s+1,s+q+1);
for(int i=1,nt=0,u=1,v=1,g;i<=q;i++){
if(cha[s[i].t].t) continue;
g=lca(s[i].u,s[i].v);
while(nt<s[i].t) timego(++nt);
while(nt>s[i].t) timego(q+(nt--));
query(u,s[i].u); query(v,s[i].v);
change(g); ans[s[i].t]=now; change(g);
u=s[i].u; v=s[i].v;
}
for(int i=1;i<=q;i++)
if(!cha[i].t) printf("%lld\n",ans[i]);
return 0;
}

UOJ #58 【WC2013】 糖果公园的更多相关文章

  1. [BZOJ3052][UOJ#58][WC2013]糖果公园

    [BZOJ3052][UOJ#58][WC2013]糖果公园 试题描述 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来 ...

  2. BZOJ3052/UOJ#58 [wc2013]糖果公园 莫队 带修莫队 树上莫队

    原文链接https://www.cnblogs.com/zhouzhendong/p/BZOJ3052.html 题目传送门 - BZOJ3052 题目传送门 - UOJ#58 题意 给定一棵树,有 ...

  3. bzoj 3052: [wc2013]糖果公园 带修改莫队

    3052: [wc2013]糖果公园 Time Limit: 250 Sec  Memory Limit: 512 MBSubmit: 506  Solved: 189[Submit][Status] ...

  4. 洛谷 P4074 [WC2013]糖果公园 解题报告

    P4074 [WC2013]糖果公园 糖果公园 树上待修莫队 注意一个思想,dfn序处理链的方法,必须可以根据类似异或的东西,然后根据lca分两种情况讨论 注意细节 Code: #include &l ...

  5. AC日记——[WC2013]糖果公园 cogs 1817

    [WC2013]糖果公园 思路: 带修改树上莫队(模板): 来,上代码: #include <cmath> #include <cstdio> #include <cst ...

  6. COGS1817. [WC2013]糖果公园

    1817. [WC2013]糖果公园 ★★★☆   输入文件:park.in   输出文件:park.out   简单对比时间限制:8 s   内存限制:512 MB [题目描述] Candyland ...

  7. 【BZOJ3052】[wc2013]糖果公园 带修改的树上莫队

    [BZOJ3052][wc2013]糖果公园 Description Input Output Sample Input Sample Input Sample Output 84 131 27 84 ...

  8. 【BZOJ】3052: [wc2013]糖果公园 树分块+带修改莫队算法

    [题目]#58. [WC2013]糖果公园 [题意]给定n个点的树,m种糖果,每个点有糖果ci.给定n个数wi和m个数vi,第i颗糖果第j次品尝的价值是v(i)*w(j).q次询问一条链上每个点价值的 ...

  9. 【Luogu P4074】[WC2013]糖果公园(树上带修改莫队)

    题目描述 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引来了许多贪吃的小朋友来糖果公园游玩. 糖果公园的结构十分奇特,它由 \(n\) 个游 ...

  10. BZOJ.3052.[WC2013]糖果公园(树上莫队 带修改莫队)

    题目链接 BZOJ 当然哪都能交(都比在BZOJ交好),比如UOJ #58 //67376kb 27280ms //树上莫队+带修改莫队 模板题 #include <cmath> #inc ...

随机推荐

  1. SQL语句优化

    (1)      选择最有效率的表名顺序 ( 只在基于规则的优化器中有效 ) : ORACLE 的解析器按照从右到左的顺序处理 FROM 子句中的表名, FROM 子句中写在最后的表 ( 基础表dri ...

  2. YYModel 源码解读(二)之NSObject+YYModel.h (5)

    好了,之前的博文中详细的解释了一些辅助的类和辅助的函数,接下来就是使用它们来实现酷炫功能的时候,正所谓磨刀不误砍柴工啊 我们先把总的功能罗列出来 1. json转字典              + ( ...

  3. 2、C#核心编程结构

     本学习主要参考Andrew Troelsen的C#与.NET4高级程序设计,这小节主要述说以下几个东西: Hello World的Main方法: 利用VS2010新建一个控制台应用程序Hello W ...

  4. LCS记录

    如题:求两个序列的最长公共序列.(如:"ABCBDAB"与"BCDB"最长公共序列为"BCDB")代码如下: #define MAX_SIZ ...

  5. Visual Studio问题集锦:coloader80.dll未正确安装

    问题 今天在修改之前的一个项目的时候报了一个错,大概内容如下: 有一个 Visual Studio 的 DLL 文件(coloader80.dll)未正确安装.请通过"控制面板"中 ...

  6. Java接口响应超时监控

    为什么要监控 服务化接口是提供服务的,接口正确性.稳定性是最最重要的,在保证正确的同时需要尽量提高接口响应时间. 有的团队会有专门的工具来对系统响应时间.吞吐量做监控,但如果团队没有这种"待 ...

  7. Python ZIP 文件创建与读取

    Automate the Boring Stuff 学习笔记 02 Python 内置的 zipfile 模块可以对文件(夹)进行ZIP格式的压缩和读取操作.要进行相关操作,首先需要实例化一个 Zip ...

  8. Node节点

    1.Node:节点元素节点->HTML标签文本节点->文字 但是在标准浏览器(除了IE6~8)中会把空格和换行都当做文本节点来处理注释节点->注释document2.节点的特征元素节 ...

  9. css单行文本与多行溢出文本的省略号问题

    在文字布局和代码编写过程中遇到文本溢出是常有的事,下面总结一下对于单行文本溢出和多行文本溢出省略号的处理. 一.单行文本省略号 <p class="text1"> 这是 ...

  10. Android 手机卫士--导航界面1的布局编写

    本文地址:http://www.cnblogs.com/wuyudong/p/5943005.html,转载请注明出处. 本文实现导航界面1的布局的实现,效果如下图所示: 首先分析所使用的布局样式: ...