好写好调的莫队算法,就算上树了仍然好写好调。

传送门

http://uoj.ac/problem/58

简要做法

将树按照dfs序分块,然后将询问按照(u所在块,v所在块,时间)作为关键字进行排序,依次转移。

转移只需依次把u,v移动到目标位置,将经过的点的标记翻转,同时每种颜色统计出现次数。

细节

转移的时候用了一个trick,把点权转换为边权,每个点代表它向父亲的边,于是不用考虑各种边界情况,处理询问的时候再将LCA加上即可。

具体方法:将端点u转移到端点v(此处uv的含义与询问的uv含义不同)时,先将u,v调整到同一深度,然后暴力向上走直到相遇。

其他

按照【王室联邦】的方法分块会更快一些。

具体参见vfk博客:http://vfleaking.blog.163.com/blog/static/174807634201311011201627/

一开始我的分块方法是错的:dfs,依次进栈,size大于块大小时弹栈,这样会导致同一个块中节点分散,于是T到飞起。

(调了好几次参数仍然跑不过同学的代码

代码

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. typedef pair<int,int> P;
  5. const int MAXN=100005, MAXB=1e7, S=1600;
  6. char BUF[MAXB], *cp=BUF;
  7. void rd(int &x){
  8. x=0;
  9. while(*cp<'0'||'9'<*cp) cp++;
  10. while('0'<=*cp&&*cp<='9') x=x*10+*cp-'0', cp++;
  11. }
  12. int N, M, K, ne, nq, no, top, tot, ord;
  13. int vis[MAXN], V[MAXN], W[MAXN], co[MAXN], n[MAXN], st[MAXN];
  14. int m[MAXN], fa[MAXN], d[MAXN], dfn[MAXN], be[MAXN], lca[MAXN], f[MAXN];
  15. ll sum, ans[MAXN];
  16. vector<P> ql[MAXN];
  17. int find(int x){return x==f[x]?x:(f[x]=find(f[x]));}
  18. void unite(int u, int v){f[find(u)]=find(v);}
  19. struct Edge{Edge *nxt; int to;}E[MAXN<<1],*hd[MAXN];
  20. void adde(int u, int v){
  21. E[ne].to=v;E[ne].nxt=hd[u];hd[u]=&E[ne++];
  22. E[ne].to=u;E[ne].nxt=hd[v];hd[v]=&E[ne++];
  23. }
  24. void addq(int u, int v, int i){ql[u].push_back(P(v,i));ql[v].push_back(P(u,i));}
  25. void dfs(int u, int p){
  26. vis[u]=1; dfn[u]=ord++; fa[u]=p; d[u]=d[p]+1;
  27. for(Edge *e=hd[u]; e; e=e->nxt){
  28. int v=e->to;
  29. if(v!=p){
  30. dfs(v,u); unite(v,u);
  31. }
  32. }
  33. for(int i=0; i<ql[u].size(); ++i)
  34. if(vis[ql[u][i].first]) lca[ql[u][i].second]=find(ql[u][i].first);
  35. }
  36. struct Qry{
  37. int l, r, t, id;
  38. bool operator<(const Qry &o)const{
  39. if(be[l]==be[o.l]) return be[r]==be[o.r]?((be[r]&1)?t>o.t:t<o.t):((be[l]&1)?be[r]>be[o.r]:be[r]<be[o.r]);
  40. return be[l]<be[o.l];
  41. }
  42. }Q[MAXN];
  43. struct Op{int x, y;}O[MAXN];
  44. inline void mdf(int x, int y){
  45. if(co[x]!=y&&m[x]){
  46. sum+=(ll)V[y]*W[n[y]+1]-(ll)V[co[x]]*W[n[co[x]]];
  47. n[y]++; n[co[x]]--; if(n[2]==-1) exit(233);
  48. }
  49. }
  50. inline void flip(int x){
  51. if(!m[x]) m[x]=1, sum+=(ll)V[co[x]]*W[++n[co[x]]];
  52. else m[x]=0, sum-=(ll)V[co[x]]*W[n[co[x]]--];
  53. }
  54. void tr(int u, int v){
  55. while(d[v]>d[u]) flip(v),v=fa[v];
  56. while(d[u]>d[v]) flip(u),u=fa[u];
  57. while(u!=v) flip(v),v=fa[v],flip(u),u=fa[u];
  58. }
  59. int main(){
  60. fread(BUF, 1, MAXB, stdin);
  61. rd(N),rd(M),rd(K);
  62. for(int i=1; i<=M; ++i) rd(V[i]);
  63. for(int i=1; i<=N; ++i) rd(W[i]);
  64. for(int i=1,u,v; i<N; ++i) rd(u),rd(v),adde(u,v);
  65. for(int i=1; i<=N; ++i) rd(co[i]);
  66. for(int i=0,t,x,y; i<K; ++i){
  67. rd(t),rd(x),rd(y);
  68. if(t==1) addq(x,y,nq),Q[nq].l=x,Q[nq].r=y,Q[nq].id=nq,Q[nq].t=no,nq++;
  69. else O[no].x=x,O[no].y=y,no++;
  70. }
  71. for(int i=1; i<=N; ++i) f[i]=i;
  72. dfs(1,0); tot++; while(top) be[st[--top]]=tot;
  73. for(int i=0; i<nq; ++i) if(dfn[Q[i].l]>dfn[Q[i].r]) swap(Q[i].l,Q[i].r);
  74. for(int i=1; i<=N; ++i) be[i]=dfn[i]/S;
  75. sort(Q,Q+nq);
  76. for(int i=0,l=1,r=1,t=0; i<nq; ++i){
  77. tr(l,Q[i].l); l=Q[i].l;
  78. tr(r,Q[i].r); r=Q[i].r;
  79. for(;t<Q[i].t;++t) mdf(O[t].x,O[t].y),swap(co[O[t].x],O[t].y);
  80. for(;t>Q[i].t;)--t,mdf(O[t].x,O[t].y),swap(co[O[t].x],O[t].y);
  81. flip(lca[Q[i].id]); ans[Q[i].id]=sum; flip(lca[Q[i].id]);
  82. }
  83. for(int i=0; i<nq; ++i) printf("%lld\n", ans[i]);
  84. return 0;
  85. }

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

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

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

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

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

  3. [BZOJ 3052] [wc2013] 糖果公园 【树上莫队】

    题目链接:BZOJ - 3052 题目分析 这道题就是非常经典的树上莫队了,并且是带修改的莫队. 带修改的莫队:将询问按照 左端点所在的块编号为第一关键字,右端点所在的块为第二关键字,位于第几次修改之 ...

  4. BZOJ 3052: [wc2013]糖果公园 | 树上莫队

    题目: UOJ也能评测 题解 请看代码 #include<cstdio> #include<algorithm> #include<cstring> #includ ...

  5. bzoj 3052: [wc2013]糖果公园【树上带修改莫队】

    参考:http://blog.csdn.net/lych_cys/article/details/50845832 把树变成dfs括号序的形式,注意这个是不包含lca的(除非lca是两点中的一个) 然 ...

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

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

  7. 【BZOJ】3052: [wc2013]糖果公园

    http://www.lydsy.com/JudgeOnline/problem.php?id=3052 题意:n个带颜色的点(m种),q次询问,每次询问x到y的路径上sum{w[次数]*v[颜色]} ...

  8. 【BZOJ3052】【UOJ#58】【WC2013】糖果公园(树上莫队)

    [BZOJ3052][UOJ#58][WC2013]糖果公园(树上莫队) 题面 UOJ 洛谷 Candyland 有一座糖果公园,公园里不仅有美丽的风景.好玩的游乐项目,还有许多免费糖果的发放点,这引 ...

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

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

随机推荐

  1. hdu3507 Print Article(斜率优化入门)(pascal)

    Problem Description Zero has an old printer that doesn't work well sometimes. As it is antique, he s ...

  2. 【loj6038】「雅礼集训 2017 Day5」远行 树的直径+并查集+LCT

    题目描述 给你 $n$ 个点,支持 $m$ 次操作,每次为以下两种:连一条边,保证连完后是一棵树/森林:询问一个点能到达的最远的点与该点的距离.强制在线. $n\le 3\times 10^5$ ,$ ...

  3. Day 2 while循环 编码 and or not

    1.判断下列逻辑语句的True,False. 1)1 > 1 or 3 < 4 or 4 > 5 and 2 > 1 and 9 > 8 or 7 < 6 Flas ...

  4. React安装React Devtools调试工具

    在运行一个React项目的时候浏览器控制台会提醒你去安装react devtools调试工具. Download the React DevTools for a better development ...

  5. (转)slf4j+logback将日志输出到控制台

    因为博主不允许转载...这边做链接记录 http://blog.csdn.net/gsycwh/article/details/52972946

  6. 洛谷 P2951 [USACO09OPEN]捉迷藏Hide and Seek

    题目戳 题目描述 Bessie is playing hide and seek (a game in which a number of players hide and a single play ...

  7. 函数式编程(1)-高阶变成(3)-sorted

    sorted 排序算法 排序也是在程序中经常用到的算法.无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小.如果是数字,我们可以直接比较,但如果是字符串或者两个dict呢?直接比较数学上的大 ...

  8. 解题:JLOI 2016 侦查守卫

    题面 经典的$cov-unc$树形dp(这词是你自己造的吧=.=) 设$cov[i][j]$表示覆盖完$i$的子树后至少向外再覆盖$j$层的最小代价,$unc[i][j]$表示$i$的子树中还剩下至少 ...

  9. BNU-2017.7.5排位赛3总结

    链接:https://www.bnuoj.com/v3/contest_show.php?cid=9148#info A题 满足条件的只有(1,2,4),(1,2,6),(1,3,6),所以先满足4, ...

  10. OpenCV---开闭操作

    一:开操作(先腐蚀后膨胀) 特点:消除噪点,去除小的干扰块,而不影响原来的图像 import cv2 as cv import numpy as np def camp(val1,val2): pv ...