对节点按编号分块。设f[i][j]为修改j号点对第i块的影响,计算f[i][]时dfs一遍即可。记录每一整块的sum。修改时对每一块直接更新sum,同时用dfs序上的树状数组维护子树和。查询时累加整块区间的sum,剩余部分bit上暴力查询。分析一下复杂度。设块大小为k,计算f数组的复杂度为O(n2/k),修改复杂度为O(nm/k+mlogn),查询复杂度O(nm/k+mklogn)。不妨设nm同阶,则k=sqrt(n/logn)时最优,总复杂度O(n·sqrt(nlogn))。然而真的这样的话f空间不够反正直接开sqrt(n)就过了。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cmath>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<algorithm>
  7. using namespace std;
  8. #define ll unsigned long long
  9. #define N 100010
  10. #define BLOCK 320
  11. char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<''||c>'')) c=getchar();return c;}
  12. int gcd(int n,int m){return m==?n:gcd(m,n%m);}
  13. int read()
  14. {
  15. int x=,f=;char c=getchar();
  16. while (c<''||c>'') {if (c=='-') f=-;c=getchar();}
  17. while (c>=''&&c<='') x=(x<<)+(x<<)+(c^),c=getchar();
  18. return x*f;
  19. }
  20. int n,m,p[N],dfn[N],size[N],root,t,cnt;
  21. int block,num,L[BLOCK],R[BLOCK],pos[N],f[BLOCK][N];
  22. ll sum[BLOCK],tree[N],a[N];
  23. struct data{int to,nxt;
  24. }edge[N<<];
  25. void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
  26. void add(int k,int x){while (k<=n) tree[k]+=x,k+=k&-k;}
  27. ll query(int k){ll s=;while (k) s+=tree[k],k-=k&-k;return s;}
  28. void calc(int k,int x,int from,int cnt)
  29. {
  30. if (k>=L[x]&&k<=R[x]) cnt++;
  31. f[x][k]=cnt;
  32. for (int i=p[k];i;i=edge[i].nxt)
  33. if (edge[i].to!=from) calc(edge[i].to,x,k,cnt);
  34. }
  35. void dfs(int k,int from)
  36. {
  37. dfn[k]=++cnt;size[k]=;
  38. for (int i=p[k];i;i=edge[i].nxt)
  39. if (edge[i].to!=from) dfs(edge[i].to,k),size[k]+=size[edge[i].to];
  40. }
  41. int main()
  42. {
  43. #ifndef ONLINE_JUDGE
  44. freopen("bzoj4765.in","r",stdin);
  45. freopen("bzoj4765.out","w",stdout);
  46. const char LL[]="%I64u\n";
  47. #else
  48. const char LL[]="%llu\n";
  49. #endif
  50. n=read(),m=read();
  51. for (int i=;i<=n;i++) a[i]=read();
  52. block=sqrt(n);num=(n-)/block+;
  53. for (int i=;i<=num;i++)
  54. {
  55. L[i]=(i-)*block+,R[i]=min(n,i*block);
  56. for (int j=L[i];j<=R[i];j++)
  57. pos[j]=i;
  58. }
  59. for (int i=;i<=n;i++)
  60. {
  61. int x=read(),y=read();
  62. if (!x) root=y;
  63. else addedge(x,y),addedge(y,x);
  64. }
  65. for (int i=;i<=num;i++) calc(root,i,root,);
  66. dfs(root,root);
  67. for (int i=;i<=n;i++) add(dfn[i],a[i]);
  68. for (int i=;i<=n;i++) sum[pos[i]]+=query(dfn[i]+size[i]-)-query(dfn[i]-);
  69. while (m--)
  70. {
  71. int op=read();
  72. if (op==)
  73. {
  74. int x=read(),y=read();
  75. y-=a[x];
  76. add(dfn[x],y);
  77. for (int i=;i<=num;i++) sum[i]+=(ll)f[i][x]*y;
  78. a[x]+=y;
  79. }
  80. else
  81. {
  82. int l=read(),r=read();
  83. ll ans=;
  84. if (pos[l]==pos[r])
  85. {
  86. for (int i=l;i<=r;i++)
  87. ans+=query(dfn[i]+size[i]-)-query(dfn[i]-);
  88. }
  89. else
  90. {
  91. for (int i=pos[l]+;i<pos[r];i++)
  92. ans+=sum[i];
  93. for (int i=l;i<=R[pos[l]];i++)
  94. ans+=query(dfn[i]+size[i]-)-query(dfn[i]-);
  95. for (int i=L[pos[r]];i<=r;i++)
  96. ans+=query(dfn[i]+size[i]-)-query(dfn[i]-);
  97. }
  98. printf(LL,ans);
  99. }
  100. }
  101. return ;
  102. }

BZOJ4765 普通计算姬(分块+树状数组)的更多相关文章

  1. [BZOJ4765]普通计算姬(分块+树状数组)

    4765: 普通计算姬 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 1725  Solved: 376[Submit][Status][Discus ...

  2. BZOJ 4765: 普通计算姬 (分块+树状数组)

    传送门 解题思路 树上的分块题,,对于修改操作,每次修改只会对他父亲到根这条链上的元素有影响:对于查询操作,每次查询[l,r]内所有元素的子树,所以就考虑dfn序,进标记一次,出标记一次,然后子树就是 ...

  3. BZOJ 4765: 普通计算姬 [分块 树状数组 DFS序]

    传送门 题意: 一棵树,支持单点修改和询问以$[l,r]$为根的子树的权值和的和 只有我这种不会分块的沙茶不会做这道题吗? 说一点总结: 子树和当然上$dfs$序了,询问原序列一段区间所有子树和,对原 ...

  4. bzoj 4765 普通计算姬(树状数组 + 分块)

    http://www.lydsy.com/JudgeOnline/problem.php?id=4765 很nice的一道题啊(可能是因为卡了n久终于做出来了 题意就是给你一棵带点权的有根树,sum( ...

  5. 【bzoj2141】排队 分块+树状数组

    题目描述 排排坐,吃果果,生果甜嗦嗦,大家笑呵呵.你一个,我一个,大的分给你,小的留给我,吃完果果唱支歌,大家乐和和.红星幼儿园的小朋友们排起了长长地队伍,准备吃果果.不过因为小朋友们的身高有所区别, ...

  6. 【分块+树状数组】codechef November Challenge 2014 .Chef and Churu

    https://www.codechef.com/problems/FNCS [题意] [思路] 把n个函数分成√n块,预处理出每块中各个点(n个)被块中函数(√n个)覆盖的次数 查询时求前缀和,对于 ...

  7. 【BZOJ 3295】动态逆序对 - 分块+树状数组

    题目描述 给定一个1~n的序列,然后m次删除元素,每次删除之前询问逆序对的个数. 分析:分块+树状数组 (PS:本题的CDQ分治解法见下一篇) 首先将序列分成T块,每一块开一个树状数组,并且先把最初的 ...

  8. 【bzoj3744】Gty的妹子序列 分块+树状数组+主席树

    题目描述 我早已习惯你不在身边, 人间四月天 寂寞断了弦. 回望身后蓝天, 跟再见说再见…… 某天,蒟蒻Autumn发现了从 Gty的妹子树(bzoj3720) 上掉落下来了许多妹子,他发现 她们排成 ...

  9. 2018.06.30 BZOJ4765: 普通计算姬(dfs序+分块+树状数组)

    4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MB Description "奋战三星期,造台计算机".小G响应号召,花了三小时 ...

随机推荐

  1. 成都Uber优步司机奖励政策(1月28日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  2. 宁波Uber优步司机奖励政策(12月21日到12月27日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  3. LeetCode: 60. Permutation Sequence(Medium)

    1. 原题链接 https://leetcode.com/problems/permutation-sequence/description/ 2. 题目要求 给出整数 n和 k ,k代表从1到n的整 ...

  4. MyBatis-MBG(MyBatis Generator)

    1.添加jar包 <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>m ...

  5. Redis系列五 Redis持久化

    Redis持久化 一.RDB(Redis DataBase) 1.介绍 在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里. Red ...

  6. Net Core学习笔记

    Net Core 官网:https://dotnet.github.io/ Net Core Api: https://docs.microsoft.com/en-us/dotnet/api/?vie ...

  7. Siki_Unity_2-1_API常用方法和类详细讲解(上)

    Unity 2-1 API常用方法和类详细讲解(上) 任务1&2:课程前言.学习方法 && 开发环境.查API文档 API: Application Programming I ...

  8. leetcode-回文链表

    请判断一个链表是否为回文链表. 示例 1: 输入: 1->2 输出: false 示例 2: 输入: 1->2->2->1 输出: true 进阶:你能否用 O(n) 时间复杂 ...

  9. sparksql读写hbase

    //写入hbase(hfile方式) org.apache.hadoop.hbase.client.Connection conn = null; try { SparkLog.debug(" ...

  10. browsersync 插件

    自从发现了这个 browsersync 插件 ... 在也不用每次改一行代码就去手动刷新 HTML 页面了省去了很多繁琐的操作,当有多个显示器的时候,更加的方便,在IDEA上编辑代码之后,点击 com ...