Description

题库链接

给你一棵 $n$ 个节点,有 $m$种颜色的树。每个节点上有一个颜色。定义一条树上路径的价值为

$sum_c V_c(\sum_{i=1}^{tim_c}W_i)$

其中 $V,W$已经给出, $tim_c$ 表示路径上 $c$ 颜色的节点数。

现在给出 $q$ 个操作,让你实现:

  1. 修改节点颜色;
  2. 询问树上路径的价值。

$1\leq n,m,q\leq 100000$

转载自Navi_Awson

如果这题出在序列上而不是在树上,很容易用莫队求解。

考虑用类似的方法,我们将树分块,采用[SCOI 2005]王室联邦的方法。

对于树上分块的复杂度和块的大小的选取可以参见ljh的博客,这里摘出了一些:

设 $block_{num}$ 为块数, $block_{size}$ 为块的大小,则有 $block_{num}\times block_{size}=n$ ,在证明中我们假设 $n,q$ 同阶。
设块对 $(block_i,block_j)$ ,易知这样的块对不会超过 $block_{size}^2$ 个。
对于块对内的操作:我们考虑总复杂度,左端点共移动至多 $O(q\times block_{size})$ ,右端点亦是。时间共移动至多 $O(block_{num}^2\times q)$ 。故这一部分的复杂度为 $O(n\times(block_{size}+block_{num}^2))$ 。
对于块与块之间的操作,不超过 $block_{num}^2$ 次:左端第移动一次,最多 $O(n)$ ,右端点亦是如此。时间最多移动 $O(q)=O(n)$ 。故这一部分复杂度为 $O(block_{num}^2\times n)$。
故总复杂度为 $O(n\times(block_{size}+block_{num}^2))$。
可以证明当 $block_{size}=n^{\frac{2}{3}}$ 时, $block_{num}=n^{\frac{1}{3}}$ ,复杂度最优,为 $O(n^{\frac{5}{3}})$ 。

至于莫队的操作,就是将序列中移动左右端点变成在树上移动路径的两个端点。对于修改,我们同样是模拟时间倒流和消逝。

那么怎么去移动结点来保证提取出路径?

考虑我们树上的所有结点,实际上可以认为是 $0/1$ 状态——计入答案或者未计入答案。

考虑用类似于异或的思想来执行操作,比如:计入答案再从答案中去掉,等于异或了两次 $1$ ,就等于原来的数。假设这次的起点、终点为 $u,v$ ,上次为 $x,y$ ,那么可以对 $x$ 到 $u$ 的路径、 $v$ 到 $y$ 的路径进行一次取 $xor$ 操作。注意的是对 $lca$ 不做处理,这样就能保证每次操作之后图上打上标记的点只在 $(u,lca)$和 $(v,lca)$ 的路径上(不包括 $lca$ )。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<algorithm>
  5. #include<cmath>
  6. using namespace std;
  7. typedef long long lol;
  8. struct ZYYS
  9. {
  10. int x,y,p,id;
  11. }p[],q[];
  12. struct Node
  13. {
  14. int next,to;
  15. }edge[];
  16. int num,head[],block[],tot,size[],son[],block_size,block_num,cnt,s[];
  17. int top[],dfn[],dep[],fa[],rev[],c[],n,m,Q,pre[],cntp,cntq;
  18. int curl,curr,curp;
  19. lol sum,v[],w[],ans[];
  20. bool cmp(ZYYS a,ZYYS b)
  21. {
  22. if (block[a.x]==block[b.x])
  23. {
  24. if (block[a.y]==block[b.y]) return a.id<b.id;
  25. else return block[a.y]<block[b.y];
  26. }
  27. else return block[a.x]<block[b.x];
  28. }
  29. void add(int u,int v)
  30. {
  31. num++;
  32. edge[num].next=head[u];
  33. head[u]=num;
  34. edge[num].to=v;
  35. }
  36. void dfs1(int x,int pa)
  37. {int i;
  38. int bot=tot;
  39. fa[x]=pa;
  40. size[x]=;
  41. dep[x]=dep[pa]+;
  42. for (i=head[x];i;i=edge[i].next)
  43. {
  44. int v=edge[i].to;
  45. if (v==pa) continue;
  46. dfs1(v,x);
  47. if (size[son[x]]<size[v]) son[x]=v;
  48. size[x]+=size[v];
  49. if (tot-bot>=block_size)
  50. {
  51. ++cnt;
  52. while (tot>bot)
  53. {
  54. block[s[tot--]]=cnt;
  55. }
  56. }
  57. }
  58. s[++tot]=x;
  59. }
  60. void dfs2(int x,int pa,int tp)
  61. {int i;
  62. top[x]=tp;
  63. dfn[x]=++tot;
  64. if (son[x]) dfs2(son[x],x,tp);
  65. for (i=head[x];i;i=edge[i].next)
  66. {
  67. int v=edge[i].to;
  68. if (v==pa||v==son[x]) continue;
  69. dfs2(v,x,v);
  70. }
  71. }
  72. int get_lca(int x,int y)
  73. {
  74. while (top[x]!=top[y])
  75. {
  76. if (dep[top[x]]<dep[top[y]]) swap(x,y);
  77. x=fa[top[x]];
  78. }
  79. if (dep[x]<dep[y]) return x;
  80. return y;
  81. }
  82. void reverse(int x)
  83. {
  84. if (rev[x]) sum-=v[c[x]]*w[s[c[x]]],s[c[x]]--;
  85. else s[c[x]]++,sum+=v[c[x]]*w[s[c[x]]];
  86. rev[x]^=;
  87. }
  88. void update(int x,int y)
  89. {
  90. if (rev[x]) reverse(x),c[x]=y,reverse(x);
  91. else c[x]=y;
  92. }
  93. void move(int x,int y)
  94. {
  95. while (x!=y)
  96. {
  97. if (dep[x]<dep[y]) swap(x,y);
  98. reverse(x);
  99. x=fa[x];
  100. }
  101. }
  102. int main()
  103. {int i,uu,vv,opt,x,y;
  104. cin>>n>>m>>Q;
  105. for (i=;i<=m;i++)
  106. scanf("%lld",&v[i]);
  107. for (i=;i<=n;i++)
  108. scanf("%lld",&w[i]);
  109. block_size=pow(n,0.666667);
  110. block_num=n/block_size;
  111. for (i=;i<n;i++)
  112. {
  113. scanf("%d%d",&uu,&vv);
  114. add(uu,vv);add(vv,uu);
  115. }
  116. for (i=;i<=n;i++)
  117. {
  118. scanf("%d",&c[i]);
  119. pre[i]=c[i];
  120. }
  121. dfs1(,);
  122. ++cnt;
  123. while (tot)
  124. {
  125. block[s[tot--]]=cnt;
  126. }
  127. tot=;
  128. memset(s,,sizeof(s));
  129. dfs2(,,);
  130. for (i=;i<=Q;i++)
  131. {
  132. scanf("%d",&opt);
  133. if (opt==)
  134. {
  135. scanf("%d%d",&x,&y);
  136. p[++cntp]=(ZYYS){x,y,pre[x],};
  137. pre[x]=y;
  138. }
  139. else
  140. {
  141. scanf("%d%d",&x,&y);
  142. q[++cntq]=(ZYYS){x,y,cntp,cntq};
  143. }
  144. }
  145. sort(q+,q+cntq+,cmp);
  146. curl=;curr=;curp=;
  147. for (i=;i<=cntq;i++)
  148. {
  149. while (curp<q[i].p) {curp++;update(p[curp].x,p[curp].y);}
  150. while (curp>q[i].p) {update(p[curp].x,p[curp].p);curp--;}
  151. move(curl,q[i].x);curl=q[i].x;
  152. move(curr,q[i].y);curr=q[i].y;
  153. int lca=get_lca(curl,curr);
  154. reverse(lca);
  155. ans[q[i].id]=sum;
  156. reverse(lca);
  157. }
  158. for (i=;i<=cntq;i++)
  159. {
  160. printf("%lld\n",ans[i]);
  161. }
  162. }

[WC2013]糖果公园的更多相关文章

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

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

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

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

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

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

  4. COGS1817. [WC2013]糖果公园

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

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

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

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

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

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

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

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

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

  9. BZOJ3052:[WC2013]糖果公园(树上莫队)

    Description Input Output Sample Input 4 3 51 9 27 6 5 12 33 13 41 2 3 21 1 21 4 20 2 11 1 21 4 2 Sam ...

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

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

随机推荐

  1. 用 Go 编写一个简单的 WebSocket 推送服务

    用 Go 编写一个简单的 WebSocket 推送服务 本文中代码可以在 github.com/alfred-zhong/wserver 获取. 背景 最近拿到需求要在网页上展示报警信息.以往报警信息 ...

  2. Beta冲刺第七天

    一.昨天的困难 没有困难. 二.今天进度 1.林洋洋:MD图片上传,修复权限问题,修复本地存储判空问题,修复协作申请没有过滤问题. 2.黄腾达:添加文件链接和邀请链接复制功能,协作树界面优化. 3.张 ...

  3. Beat冲刺报告---Day0

    Beta阶段报告---Day0 1.需要改进完善的功能   我们上一阶段开发由于开发时间匆忙,对于爬虫耗时的优化没有考虑.优化的空间我在Alpha阶段的总结报告里说过,具体看下图.   这张图显示出爱 ...

  4. 201621123044《JAVA程序设计》第一周学习总结

    1. 本周学习总结 1.了解了JAVA的诞生以及发展历史简介.JAVA语言的特点,以及JAVA的电脑安装以及环境配置. 2.JAVA不仅可以用eclipse进行编写,也可以在记事本和notepad++ ...

  5. SENet

     \(\bf F_{tr}\) 为标准卷积操作 \(\bf F_{sq}\) 为 Global Average Pooling \(\bf F_{ex}\) 为两层全连接网络(可以看做两个1×1卷积 ...

  6. 浏览器端类EXCEL表格插件 - 智表ZCELL产品V1.0.0.1版本发布

    智表的优势 智表兼容与依赖 ZCELL 基于jQuery V1.11.3版本研发,兼容性依赖于jQuery自身的兼容性. 经过验证,目前IE.火狐.谷歌.360等主流浏览器均可以正常使用. 智表下载 ...

  7. Web移动端适配总结

    移动端适配的相关概念以及几种方案总结 适配相关概念 布局视口(layout viewport):html元素的上一级容器即顶级容器,用于解决页面在手机上显示的问题.大部分移动设备都将这个视口分辨率设置 ...

  8. J2ee入门:servlet-mapping的映射配置

    <servlet-mapping>元素在Servlet和URL样式之间定义一个映射.它包含了两个子元素<servlet- name>和<url-pattern> & ...

  9. 【第二十一篇】手C# MVC 微信授权登录 OAuth2.0授权登录

    首先一定要熟读,最起码过一遍微信开发者文档 微信开发者文档 文档写的很清楚 授权登录四步走 在正文开始前,我得讲清楚一个事情 敲黑板,划重点:微信一共有两个 access_token 一个是7200就 ...

  10. 浅谈 Mybatis中的 ${ } 和 #{ }的区别

    好了,真正做开发也差不多一年了.一直都是看别人的博客,自己懒得写,而且也不会写博客,今天就开始慢慢的练习一下写博客吧.前段时间刚好在公司遇到这样的问题. 一.举例说明 select * from us ...