传送门

总算会树形莫队了……

上次听说树形莫队是给树分块,实在看不懂。然后用括号序列的方法做总算能弄明白了

先说一下什么是括号序列,就是在$dfs$的时候,进入的时候记录一下,出去的时候也记录一下

拿样例为例,它的括号序列就是$12443321$

那么我们扩展区间对答案的贡献是可以$O(1)$计算的

假设扩展出的点的颜色是$c$,那么变化量为$val_c*worth_{cnt_c+1}$

因为括号序列它在扩展的时候会把子树里的扫两遍,那么就可以把子树中的答案去掉了

怎么去掉呢?记录一个$vis$然后每次扫到的时候异或一下,看看是否被扫过就行了

然而有几个问题

第一,$LCA$不是路径端点的话不会被记入答案

考虑上面的括号序列,如果要从$4$到$3$那么$2$是不会被计入答案的

第二,起点不是$LCA$的话不会被记入答案

考虑上面,$u$被算了两次,刚好把自己给减掉了

所以上面的两种情况要特判

然后因为是带修莫队,所以再加上时间这一维

还有这题细节挺多的……我因为跳时间轴的时候一个地方写错WA了好久……

 //minamoto
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char sr[<<],z[];int C=-,Z;
inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
inline void print(ll x){
if(C><<)Ot();if(x<)sr[++C]=,x=-x;
while(z[++Z]=x%+,x/=);
while(sr[++C]=z[Z],--Z);sr[++C]='\n';
}
const int N=;
struct query{
int x,y,l,r,id,t;
}q[N];int q1;
struct change{int x,c;}t[N];int q2;
int n,m,L,R,T,s,Q;ll now,ans[N];
int ver[N<<],edge[N<<],head[N],Next[N<<],top[N],dfn[N],dep[N],sz[N],son[N],lis[N<<],fa[N],tot,num;
int vis[N],col[N],wor[N],cnt[N],val[N];
inline bool cmp(const query a,const query b){
if(a.l^b.l) return a.l<b.l;
if(a.r^b.r) return a.l&?a.r<b.r:a.r>b.r;
return (a.l^a.r)&?a.t<b.t:a.t>b.t;
}
inline void add(int u,int v){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
ver[++tot]=u,Next[tot]=head[v],head[v]=tot;
}
void dfs(int u){
dep[u]=dep[fa[u]]+,sz[u]=;
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v!=fa[u]){
fa[v]=u,dfs(v),sz[u]+=sz[v];
if(sz[v]>sz[son[u]]) son[u]=v;
}
}
}
void dfs(int u,int t){
top[u]=t,lis[dfn[u]=++num]=u;
if(son[u]) dfs(son[u],t);
for(int i=head[u];i;i=Next[i]){
if(ver[i]!=fa[u]&&ver[i]!=son[u]) dfs(ver[i],ver[i]);
}
lis[++num]=u;
}
inline int LCA(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
u=fa[top[u]];
}
return dep[u]<dep[v]?u:v;
}
inline void sol(int x){
int c=col[x];
(vis[x]^=)?now+=(ll)wor[++cnt[c]]*val[c]:now-=(ll)wor[cnt[c]--]*val[c];
}
inline void mdy(int i){
int u=t[i].x,x=t[i].c,y=col[u];
if(vis[u]) now+=(ll)wor[++cnt[x]]*val[x]-(ll)wor[cnt[y]--]*val[y];
t[i].c=y,col[u]=x;
}
int main(){
n=read(),m=read(),Q=read();
for(int i=;i<=m;++i) val[i]=read();
for(int i=;i<=n;++i) wor[i]=read();
for(int i=;i<n;++i){
int u=read(),v=read();add(u,v);
}
for(int i=;i<=n;++i) col[i]=read();
dfs(),dfs(,);
while(Q--){
int opt=read(),x=read(),y=read();
if(opt){if(dfn[x]>dfn[y]) swap(x,y);
q[++q1]=(query){x,y,dfn[x],dfn[y],q1,q2};
}
else t[++q2]=(change){x,y};
}
s=pow(n,q2?2.0/:1.0/);
for(int i=;i<=n;++i) q[i].l/=s,q[i].r/=s;
sort(q+,q++q1,cmp),L=dfn[q[].l],R=L-,T=;
for(int i=;i<=q1;++i){
int u=q[i].x,v=q[i].y;
int l=dfn[u],r=dfn[v],g=q[i].t;
while(L>l) sol(lis[--L]);
while(R<r) sol(lis[++R]);
while(L<l) sol(lis[L++]);
while(R>r) sol(lis[R--]);
while(T<g) mdy(++T);
while(T>g) mdy(T--);
//LCA不是路径端点的话是不会计算的
//出发点u如果不是LCA也是不会计算的
//这两个都要特判
int p=LCA(u,v);
if(u!=p){sol(u);if(v!=p) sol(p);}
ans[q[i].id]=now;
if(u!=p){sol(u);if(v!=p) sol(p);}
}
for(int i=;i<=q1;++i) print(ans[i]);
Ot();
return ;
}

洛谷P4074 [WC2013]糖果公园(莫队)的更多相关文章

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

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

  2. [洛谷P4074][WC2013]糖果公园

    题目大意:给一棵$n$个节点的树,每个点有一个值$C_i$,每次询问一条路径$x->y$,求$\sum\limits_{c}val_c\times \sum\limits_{i=1}^{cnt_ ...

  3. Machine Learning Codeforces - 940F(带修莫队) && 洛谷P4074 [WC2013]糖果公园

    以下内容未验证,有错请指正... 设块大小为T,则块数为$\frac{n}{T}$ 将询问分为$(\frac{n}{T})^2$块(按照左端点所在块和右端点所在块分块),同块内按时间从小到大依次处理 ...

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

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

  5. P4074 [WC2013]糖果公园 树上莫队带修改

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

  6. BZOJ 3052/Luogu P4074 [wc2013]糖果公园 (树上带修莫队)

    题面 中文题面,难得解释了 BZOJ传送门 Luogu传送门 分析 树上带修莫队板子题... 开始没给分块大小赋初值T了好一会... CODE #include <bits/stdc++.h&g ...

  7. LUOGU P4074 [WC2013]糖果公园 (树上带修莫队)

    传送门 解题思路 树上带修莫队,搞了两天..终于开O2+卡常大法贴边过了...bzoj上跑了183s..其实就是把树上莫队和带修莫队结合到一起,首先求出括号序,就是进一次出一次那种的,然后如果求两个点 ...

  8. Bzoj2120/洛谷P1903 数颜色(莫队)

    题面 Bzoj 洛谷 题解 考虑对操作离线后分块处理询问操作(莫队算法),将询问操作按照编号分块后左端点第一关键字,右端点第二关键字排序(分块大小为\(n^{\frac 23}\)),对于每一个询问操 ...

  9. luogu P4074 [WC2013]糖果公园

    传送门 这种题显然要用树上莫队 何为树上莫队?就是在树上跑莫队算法就是先把树分块,然后把询问离线,按照左端点所在块为第一关键字,右端点所在块为第二关键字,时间戳(如果有修改操作)为第三关键字排序,然后 ...

随机推荐

  1. 刷题常用的STL容器总结

    本文归纳总结刷题常用到STL容器以及一些标准算法,主要包括: string.vector.map.pair.unordered_map.set.queue.priority_queue.stack,以 ...

  2. 侯捷STL学习(二)--序列容器测试

    第六节:容器之分类和各种测试(四) stack不提供iterator操作,破坏了容器的独特性,先进先出. 使用容器multiset(允许元素重复) 内部是红黑树,insert操作就保证了排好了序. 标 ...

  3. 【转】rails 遇到 Could not find a JavaScript runtime execjs错误(ubuntu)

    当我运行 $rails s 遇到下面错误 sudo apt-get install python-software-properties sudo add-apt-repository ppa:chr ...

  4. DAY14-前端之Bootstrap框架

    Bootstrap介绍 Bootstrap是Twitter开源的基于HTML.CSS.JavaScript的前端框架. 它是为实现快速开发Web应用程序而设计的一套前端工具包. 它支持响应式布局,并且 ...

  5. 转载-你应该知道的 RPC 原理

    在校期间大家都写过不少程序,比如写个hello world服务类,然后本地调用下,如下所示.这些程序的特点是服务消费方和服务提供方是本地调用关系. 而一旦踏入公司尤其是大型互联网公司就会发现,公司的系 ...

  6. css实现三角形(转)

    css实现三角形 (2012-09-10 14:17:26) 标签: css 三角形 杂谈 分类: 网页制作 css实现三角形的原理是:当元素的宽高为0,边框(border)不为0时,四个角边框交界重 ...

  7. Ros学习——创建ROS消息和ROS服务

    1.rosed rosed 是 rosbash 的一部分.利用它可以直接通过package名来获取到待编辑的文件而无需指定该文件的存储路径了. rosed默认的编辑器是vim.修改其他的,打开~/.b ...

  8. cocos2d-js 浏览器与JSB内存管理机制的不同

    写这边文章的主要目的是为了理解使用cocos3d-js开发app时,浏览器调试与真机情况不一致的原因 一.浏览器中内存管理机制 HTML5版本运行时,整个游戏只存在JS脚本与一些必要的资源文件,这时候 ...

  9. Excel VBA 若要在64位系统上使用,则必须更新此项目中的代码,请检查并更新Declare语句,然后用PtrSafe属性标记它们

    在Office 2010 32位上开发的Excel VBA系统,迁移到Office 2010 64位下面,打开后使用,报下面错误: 解决办法:  在Declare 后面加PtrSafe 进行标记

  10. 一篇docker的详细技术文章

    http://www.open-open.com/lib/view/open1423703640748.html