题目描述

给出一棵n个点的树,每个点有一个点权,点权范围为1~m。支持两种操作:(1)修改一个点的点权 (2)对于一条路径,求$\sum\limits_{i=1}^m\sum\limits_{j=1}^{s_i}V_iW_j$,其中$s_i$表示这条链上权值为i的点数。

输入

输出

样例输入

4 3 5
1 9 2
7 6 5 1
2 3
3 1
3 4
1 2 3 2
1 1 2
1 4 2
0 2 1
1 1 2
1 4 2

样例输出

84
131
27
84


题解

带修改树上莫队

带修改树上莫队——普通莫队的 带修改进化版+上树树上进化版。

带修改莫队:每块大小$n^{\frac 23}$,分别以左端点所在块、右端点所在块、时间(这次询问之前的修改次数)为第一、二、三关键字排序,然后暴力移动三个指针。

树上莫队:分块方法改成树分块(树分块方法参考 王室联邦),自然序改成DFS序(然而带修改莫队用不到自然序,这里只是提一嘴),暴力移动指针。这里可以把点权加到边权上(链上LCA只在统计答案是算上),以避免特判。

把它们结合起来本题就做完了。把树分块,然后按照带修改莫队处理即可。

几点注意:

求LCA要用非朴素LCA(因为不仅仅在移动指针时需要求LCA,点权加到边权上时统计答案也需要处理LCA)

修改要记录是从什么改到什么,因为有反向修改(时间指针左移)操作。

答案会爆int,故需要long long。

时间复杂度$O(n^{\frac 53})$

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #define N 100010
  5. using namespace std;
  6. const int b = 1200;
  7. typedef long long ll;
  8. int v[N] , w[N] , head[N] , to[N << 1] , next[N << 1] , ce , type[N];
  9. int fa[N][20] , deep[N] , log[N] , tot , sta[N] , top , bl[N] , num;
  10. int pc[N] , wc[N] , vc[N] , vis[N] , cnt[N];
  11. ll ans , ret[N];
  12. struct data
  13. {
  14. int lp , rp , cp , id;
  15. bool operator<(const data &a)const
  16. {
  17. return bl[lp] == bl[a.lp] ? bl[rp] == bl[a.rp] ? cp < a.cp : bl[rp] < bl[a.rp] : bl[lp] < bl[a.lp];
  18. }
  19. }a[N];
  20. void add(int x , int y)
  21. {
  22. to[++ce] = y , next[ce] = head[x] , head[x] = ce;
  23. }
  24. void dfs(int x)
  25. {
  26. int i , now = top;
  27. for(i = 1 ; (1 << i) <= deep[x] ; i ++ ) fa[x][i] = fa[fa[x][i - 1]][i - 1];
  28. for(i = head[x] ; i ; i = next[i])
  29. {
  30. if(to[i] != fa[x][0])
  31. {
  32. fa[to[i]][0] = x , deep[to[i]] = deep[x] + 1 , dfs(to[i]);
  33. if(top - now >= b)
  34. {
  35. num ++ ;
  36. while(top != now) bl[sta[top -- ]] = num;
  37. }
  38. }
  39. }
  40. sta[++top] = x;
  41. }
  42. int lca(int x , int y)
  43. {
  44. int i;
  45. if(deep[x] < deep[y]) swap(x , y);
  46. for(i = log[deep[x] - deep[y]] ; ~i ; i -- )
  47. if(deep[x] - deep[y] >= (1 << i))
  48. x = fa[x][i];
  49. if(x == y) return x;
  50. for(i = log[deep[x]] ; ~i ; i -- )
  51. if(deep[x] >= (1 << i) && fa[x][i] != fa[y][i])
  52. x = fa[x][i] , y = fa[y][i];
  53. return fa[x][0];
  54. }
  55. void rev(int x)
  56. {
  57. if(vis[x]) ans -= (ll)w[cnt[type[x]]] * v[type[x]] , cnt[type[x]] -- , vis[x] = 0;
  58. else cnt[type[x]] ++ , ans += (ll)w[cnt[type[x]]] * v[type[x]] , vis[x] = 1;
  59. }
  60. int main()
  61. {
  62. int n , m , q , i , j , x , y , opt , cc = 0 , ln = 1 , rn = 1 , now = 0;
  63. scanf("%d%d%d" , &n , &m , &q);
  64. for(i = 1 ; i <= m ; i ++ ) scanf("%d" , &v[i]);
  65. for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &w[i]);
  66. for(i = 2 ; i <= n ; i ++ ) scanf("%d%d" , &x , &y) , add(x , y) , add(y , x) , log[i] = log[i >> 1] + 1;
  67. dfs(1);
  68. while(top) bl[sta[top -- ]] = num;
  69. for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &type[i]);
  70. for(i = 1 ; i <= q ; i ++ )
  71. {
  72. scanf("%d" , &opt);
  73. if(opt)
  74. {
  75. scanf("%d%d" , &a[i - cc].lp , &a[i - cc].rp) , a[i - cc].cp = cc , a[i - cc].id = i - cc;
  76. if(bl[a[i - cc].lp] > bl[a[i - cc].rp]) swap(a[i - cc].lp , a[i - cc].rp);
  77. }
  78. else cc ++ , scanf("%d%d" , &pc[cc] , &vc[cc]) , wc[cc] = type[pc[cc]] , type[pc[cc]] = vc[cc];
  79. }
  80. for(i = cc ; i ; i -- ) type[pc[i]] = wc[i];
  81. sort(a + 1 , a + q - cc + 1);
  82. for(i = 1 ; i <= q - cc ; i ++ )
  83. {
  84. x = lca(ln , a[i].lp);
  85. for(j = ln ; j != x ; j = fa[j][0]) rev(j);
  86. for(j = a[i].lp ; j != x ; j = fa[j][0]) rev(j);
  87. x = lca(rn , a[i].rp);
  88. for(j = rn ; j != x ; j = fa[j][0]) rev(j);
  89. for(j = a[i].rp ; j != x ; j = fa[j][0]) rev(j);
  90. ln = a[i].lp , rn = a[i].rp , x = lca(ln , rn) , rev(x);
  91. while(now < a[i].cp)
  92. {
  93. now ++ ;
  94. if(vis[pc[now]]) cnt[vc[now]] ++ , ans += (ll)w[cnt[vc[now]]] * v[vc[now]] - (ll)w[cnt[wc[now]]] * v[wc[now]] , cnt[wc[now]] -- ;
  95. type[pc[now]] = vc[now];
  96. }
  97. while(now > a[i].cp)
  98. {
  99. if(vis[pc[now]]) cnt[wc[now]] ++ , ans += (ll)w[cnt[wc[now]]] * v[wc[now]] - (ll)w[cnt[vc[now]]] * v[vc[now]] , cnt[vc[now]] -- ;
  100. type[pc[now]] = wc[now];
  101. now -- ;
  102. }
  103. ret[a[i].id] = ans;
  104. rev(x);
  105. }
  106. for(i = 1 ; i <= q - cc ; i ++ ) printf("%lld\n" , ret[i]);
  107. return 0;
  108. }

【bzoj3052】[wc2013]糖果公园 带修改树上莫队的更多相关文章

  1. 【bzoj4129】Haruna’s Breakfast 带修改树上莫队+分块

    题目描述 给出一棵树,点有点权.支持两种操作:修改一个点的点权,查询链上mex. 输入 第一行包括两个整数n,m,代表树上的结点数(标号为1~n)和操作数.第二行包括n个整数a1...an,代表每个结 ...

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

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

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

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

  4. UOJ 58 (树上带修改的莫队)

    UOJ 58 糖果公园 Problem : 给一棵n个点的树,每个点上有一种颜色,对于一条路径上的点,若 i 颜色第 j 次出现对该路径权值的贡献为 w[i] * c[j], 每次询问一条路径的权值, ...

  5. 【BZOJ】2120: 数颜色 带修改的莫队算法

    [题意]给定n个数字,m次操作,每次询问区间不同数字的个数,或修改某个位置的数字.n,m<=10^4,ai<=10^6. [算法]带修改的莫队算法 [题解]对于询问(x,y,t),其中t是 ...

  6. BZOJ 2120: 数颜色 带修改的莫队算法 树状数组套主席树

    https://www.lydsy.com/JudgeOnline/problem.php?id=2120 标题里是两种不同的解法. 带修改的莫队和普通莫队比多了个修改操作,影响不大,但是注意一下细节 ...

  7. P1903 [国家集训队]数颜色 / 维护队列 带修改的莫队

    \(\color{#0066ff}{ 题目描述 }\) 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支 ...

  8. UVA - 12345 带修改的莫队

    题意显然:给出初始序列,单点修改,区间查询元素的种类. 由于时限过宽,暴力可过. 比较优秀的解法应该是莫队. 带修改的莫队题解可以看https://www.luogu.org/blog/user126 ...

  9. codeforces 940F 带修改的莫队

    F. Machine Learning time limit per test 4 seconds memory limit per test 512 megabytes input standard ...

随机推荐

  1. 添加fileinfo扩展

    首先声明:笔者用的是军哥的lnmp一键安装包!链接地址:https://lnmp.org 打开upgrade_php.sh配置文件[文件所在位置:~/lnmp1.4/include/upgrade_p ...

  2. vue-cli+ webpack 搭建项目todolist

    本文接着之前的todolist例子,通过vue-cli + webpack 搭建项目:针对于vue-cli 2.x版本,更高版本找官网https://cli.vuejs.org/guide/insta ...

  3. 【tp5.1】微信公众号授权登录及获取信息录入数据库

    微信公众号开发文档链接:https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1445241432 微信公众号授权登录分为两种: 1.以 ...

  4. PADS快捷键

    问:在pads layout中怎样显示或隐藏铺铜的效果 答: 无模命令:po 或者spo 前者是平面层 后者是混合层. 同时你可以在ctrl+alt+c 色彩项中关闭 copper . 使用 无模命令 ...

  5. python 使用生成器 来完成 监听文件输入的例子

    def tail(filename):#函数 f = open(filename,encoding='utf-8') while True: line = f.readline() if line.s ...

  6. Java学习笔记一:三步搭建Java开发环境

    Java开发环境搭建 一:安装JDK: 1.下载地址:http://www.oracle.com/technetwork/java/javase/downloads 非常显眼的下载界面 2.点击下载后 ...

  7. Kubernetes-设计理念(三)

    Kubernetes设计理念与分布式系统 分析和理解Kubernetes的设计理念可以使我们更深入的了解Kubernetes系统,更好的利用它管理分布式部署的云原生应用,另一方面也可以让我们借鉴其在分 ...

  8. C# static const和readonly区别

    Const 定义的是静态常在对象初始化的时候赋值.以后不能改变它的值.属于编译时常量. Static 定义的是静态变量.可以再外部改变它的值.. Readonly 是只读变量.属于运行时变量.可以在类 ...

  9. 1139: [POI2009]Wie

    1139: [POI2009]Wie https://www.lydsy.com/JudgeOnline/problem.php?id=1139 分析: Dijkstra.状压最短路,dis[i][j ...

  10. ORB-SLAM 代码笔记(五)Frame类

    Frame类的成员变量主要包含从摄像头获取的图像的 1. 特征点信息(关键点+描述字) 2. 尺寸不变特征所用金字塔信息,这些都定义在ORBextractor对象中 3. 词袋模型参数,用于跟踪失败情 ...