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[100001],q[100001];
 12 struct Node
 13 {
 14   int next,to;
 15 }edge[200001];
 16 int num,head[100001],block[100001],tot,size[100001],son[100001],block_size,block_num,cnt,s[100001];
 17 int top[100001],dfn[100001],dep[100001],fa[100001],rev[100001],c[100001],n,m,Q,pre[100001],cntp,cntq;
 18 int curl,curr,curp;
 19 lol sum,v[100001],w[100001],ans[100001];
 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]=1;
 41   dep[x]=dep[pa]+1;
 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]^=1;
 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=1;i<=m;i++)
106     scanf("%lld",&v[i]);
107   for (i=1;i<=n;i++)
108     scanf("%lld",&w[i]);
109   block_size=pow(n,0.666667);
110   block_num=n/block_size;
111   for (i=1;i<n;i++)
112     {
113       scanf("%d%d",&uu,&vv);
114       add(uu,vv);add(vv,uu);
115     }
116   for (i=1;i<=n;i++)
117     {
118       scanf("%d",&c[i]);
119       pre[i]=c[i];
120     }
121   dfs1(1,0);
122   ++cnt;
123   while (tot)
124     {
125       block[s[tot--]]=cnt;
126     }
127   tot=0;
128   memset(s,0,sizeof(s));
129   dfs2(1,0,1);
130   for (i=1;i<=Q;i++)
131     {
132       scanf("%d",&opt);
133       if (opt==0)
134     {
135       scanf("%d%d",&x,&y);
136       p[++cntp]=(ZYYS){x,y,pre[x],0};
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+1,q+cntq+1,cmp);
146   curl=1;curr=1;curp=0;
147   for (i=1;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=1;i<=cntq;i++)
159     {
160       printf("%lld\n",ans[i]);
161     }
162 }

转载于:https://www.cnblogs.com/Y-E-T-I/p/8781943.html

[WC2013]糖果公园相关推荐

  1. LG P4074 [WC2013] 糖果公园(带修莫队,树上莫队)

    LG P4074 [WC2013] 糖果公园 Solution 树上带修莫队,主要还是复习带修莫队和树上莫队. 带修莫队: 带修莫队要先对lll分块的序号作为第一关键字,对rrr分块的序号作为第二关键 ...

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

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

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

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

  4. luogu4074-[WC2013]糖果公园

    Description P4074 [WC2013]糖果公园 - 洛谷 | 计算机科学教育新生态 Solution 树上莫队 && 带修莫队. [模板] 各种莫队 代码 #includ ...

  5. UOJ58 【WC2013】糖果公园

    UOJ58 [WC2013]糖果公园 蒟蒻学个树上莫队都要学一晚上 树上莫队是依照dfs序的,将不过在点遍历完所有儿子后还要再进行一次打时间戳. 用这种方法,再特判一下LCA就好了. 网上的大多数方法 ...

  6. uoj#58./bzoj3052 【WC2013】糖果公园 //树上带修改莫队

    uoj#58. [WC2013]糖果公园 题意 有一棵N(<=1e5)个点的树,每个点对应M(<=1e5)种糖果中的一种. 一条路径的权值定义为∑i(Vi∗∑tij=1Wj)\sum_i ...

  7. 【WC2013】糖果公园 树上莫队

    树上莫队,将树分块,以x,y为一二关键字,以时间为第三关键字.暴力修改. #include <iostream> #include <cstdio> #include < ...

  8. P4074-[WC2013]糖果公园【树上带修莫队】

    正题 题目链接:https://www.luogu.com.cn/problem/P4074 题目大意 nnn个点的一颗数,第iii个点有一颗cic_ici​种类的糖. 第iii次获得jjj种类的糖可 ...

  9. YBTOJ洛谷P4074:糖果公园(树上莫队)

    文章目录 解析 update: 代码 所谓树上莫队,就是在树上的莫队 (逃) 传送门 解析 似乎就是树上的这道题 考虑如何转化为序列问题呢? 考虑dfs序 但是又一个问题... 似乎这条链的dfs序不 ...

最新文章

  1. IPython 更改默认字体大小
  2. rs485接口上下拉_RS485接口EMC电路设计方案
  3. java获取异常堆栈详情
  4. 教资考试 科目一 笔记小结 0227
  5. Spark Shuffle系列-----1. Spark Shuffle与任务调度之间的关系
  6. python csv 格式文件导出 中文乱码问题解决方法
  7. ZK 在XML编辑器中设置.zul文件
  8. 西安电子科技大学出版社 线性代数 参考答案 刘三阳
  9. 实用win7桌面小工具
  10. SQLyog数据库:主键外键代码添加
  11. QGIS制作导出三维模型并发布
  12. 张宇高数 第二讲 一元函数微分学(思维导图)
  13. 我将进化成一条狗(10)——长寿秘诀
  14. 冬至幻灵怎么修改服务器名字,冬至幻灵如何给自己加元宝
  15. Python Appium自动化测试 连接模拟器启动淘宝APP
  16. 如何设置Foxmail收取yahoo.com.cn和yahoo.cn以及yahoo.com等邮箱的方法
  17. 【Solidity】注意事项
  18. python-collections
  19. uva10635 Prince and Princess LCS 变 lIS
  20. PyDev Eclipse使用技巧说明

热门文章

  1. 识破面试官的套路:十个典型的面试问题剖析
  2. Linux常用命令——最详细!!!!
  3. 四川店盈通电子商务有限公司:《零售的哲学》中的最基本观点“以用户为中心”
  4. 动画特效十五:网易新闻之头部导航切换效果
  5. JZOJ1383. 奇怪的问题 (2017.8B组)
  6. Windows 11和安全启动
  7. 示波器的使用以及基本原理
  8. 声速的测量的实验原理和应用_示波器的原理和使用声速测量实验报告.docx
  9. 图像置乱之评价图像置乱度算法的选择
  10. android笔记 看过stormzhang大大的博客(关于像素,屏幕密度)