Description

"奋战三星期,造台计算机"。小G响应号召,花了三小时造了台普通计算姬。普通计算姬比普通计算机要厉害一些
。普通计算机能计算数列区间和,而普通计算姬能计算树中子树和。更具体地,小G的计算姬可以解决这么个问题
:给定一棵n个节点的带权树,节点编号为1到n,以root为根,设sum[p]表示以点p为根的这棵子树中所有节点的权
值和。计算姬支持下列两种操作:
1 给定两个整数u,v,修改点u的权值为v。
2 给定两个整数l,r,计算sum[l]+sum[l+1]+....+sum[r-1]+sum[r]
尽管计算姬可以很快完成这个问题,可是小G并不知道它的答案是否正确,你能帮助他吗?

Input

第一行两个整数n,m,表示树的节点数与操作次数。
接下来一行n个整数,第i个整数di表示点i的初始权值。
接下来n行每行两个整数ai,bi,表示一条树上的边,若ai=0则说明bi是根。
接下来m行每行三个整数,第一个整数op表示操作类型。
若op=1则接下来两个整数u,v表示将点u的权值修改为v。
若op=2则接下来两个整数l,r表示询问。
N<=10^5,M<=10^5
0<=Di,V<2^31,1<=L<=R<=N,1<=U<=N

Output

对每个操作类型2输出一行一个整数表示答案。

Sample Input

6 4
0 0 3 4 0 1
0 1
1 2
2 3
2 4
3 5
5 6
2 1 2
1 1 1
2 3 6
2 3 5

Sample Output

16
10
9

HINT

思路

分块分块再分块,

假设块的长度是m,

可以先对编号分块,预处理出每个点对每一块的贡献(即这一块中有多少个x的祖先)。

这样时间复杂度n^2/m,空间复杂度n^2/m,为了不mle,m适宜<500。

这样修改操作就可以O(n/m)完成。

考虑询问操作,中间的完整块很好处理O(n/m),但左右端的残余块难处理。

可以扫残余块中的每个点,计算它们子树和的和,大约要计算m次子树和,即查询m次。

考虑怎样很快的计算子树和。

一种是log的做法,dfs序建树状数组,修改O(logn),查询O(logn)。但是这样查询多了一个log,不优。

考虑,每次操作,修改只进行了1次,查询进行了m次。所以考虑使修改变慢,查询变快。

所以,再对dfs序进行分块即可。这样修改O(n/m),查询1次O(1),非常优越。

时间复杂度n^2/m+nm=n*(n/m+m)。所以当m=sqrt(n)的时候,时间复杂度为O(n sqrt(n))

由于这种做法常数较大,虽然是O(n sqrt(n))的,有可能比那些带log的程序要慢(这也很尴尬啊)

代码

  1 #include <cmath>
  2 #include <cstdio>
  3 #include <iostream>
  4 using namespace std;
  5 int read()
  6 {
  7     char c=getchar();int d=0,f=1;
  8     for(;c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
  9     for(;c>='0'&&c<='9';d=d*10+c-48,c=getchar());
 10     return d*f;
 11 }
 12 typedef unsigned long long ull;
 13 typedef long long ll;
 14 const int N=100002;
 15 int M,n,m,cnt,tot;
 16 int tmp[N],fa[N],bl[N],L[N],R[N],w[N*2],head[N],size[N],pos[N],t[320][N];
 17 ll s[N*2],bs[N*2],a[N*2];
 18 struct xint{int to,next;}e[N*2];
 19 inline void addedge(int x,int y)
 20 {
 21     e[++cnt]=(xint){y,head[x]};
 22     head[x]=cnt;
 23 }
 24 inline void add(int x,int s)
 25 {
 26     for(int i=R[x];i<=R[n];i+=M)a[i]+=s;
 27     for(int i=x;i<=R[x]-1;++i)a[i]+=s;
 28 }
 29 inline ll ask(int x)
 30 {
 31     int A=pos[x]+size[x]-1,B=pos[x]-1;
 32     return ((A%M)?a[L[A]-1]+a[A]:a[A])-((B%M)?a[L[B]-1]+a[B]:a[B]);
 33 }
 34 inline void dfs(int x)
 35 {
 36     tmp[bl[x]]++;
 37     for(int i=1;i<=bl[n];++i)t[i][x]=tmp[i];
 38     pos[x]=++tot;
 39     size[x]=1; s[x]=w[x];
 40     for(int i=head[x];i;i=e[i].next)
 41     {
 42         int y=e[i].to;
 43         if(y==fa[x])continue;
 44         fa[y]=x;dfs(y);
 45         size[x]+=size[y];
 46         s[x]+=s[y];
 47     }
 48     tmp[bl[x]]--;
 49 }
 50 inline void init()
 51 {
 52     n=read()+1,m=read();
 53     M=int(sqrt(n));
 54     for(int i=1;i<=n;++i)bl[i]=(i-1)/M+1;
 55     for(int i=1;i<=n;++i)L[i]=bl[i]*M-M+1,R[i]=bl[i]*M;
 56     for(int i=2;i<=n;++i)w[i]=read();
 57     for(int i=2;i<=n;++i)
 58     {
 59         int x=read()+1,y=read()+1;
 60         addedge(x,y);
 61         addedge(y,x);
 62     }
 63     dfs(1);
 64     for(int i=1;i<=n;++i)bs[bl[i]]+=s[i];
 65     for(int i=1;i<=n;++i)add(pos[i],w[i]);
 66 }
 67 inline ull solve(int x,int y)
 68 {
 69     ull res=0;
 70     if(bl[x]==bl[y])
 71     {
 72         for(int i=x;i<=y;++i)res+=ask(i);
 73         return res;
 74     }
 75     for(int i=x;i<=R[x];++i)res+=ask(i);
 76     for(int i=L[y];i<=y;++i)res+=ask(i);
 77     for(int i=bl[x]+1;i<=bl[y]-1;++i)res+=bs[i];
 78     return res;
 79 }
 80 inline void work()
 81 {
 82     while(m--)
 83     {
 84         int o=read(),x=read(),y=read();
 85         if(o==1)
 86         {
 87             x++;
 88             ll dw=y-w[x];
 89             for(int i=1;i<=bl[n];++i)
 90                 bs[i]+=dw*t[i][x];
 91             add(pos[x],dw);
 92             w[x]=y;
 93         }else
 94         if(o==2)
 95         {
 96             x++,y++;
 97             ull ans=solve(x,y);
 98             printf("%llu\n",ans);
 99         }
100     }
101 }
102 int main()
103 {
104     init();
105     work();
106 }

转载于:https://www.cnblogs.com/Blog-of-Eden/p/6685423.html

bzoj 4765: 普通计算姬相关推荐

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

    4765: 普通计算姬 Time Limit: 30 Sec  Memory Limit: 256 MB Submit: 1481  Solved: 318 [Submit][Status][Disc ...

  2. bzoj 4765 普通计算姬

    http://www.elijahqi.win/archives/3696 Description "奋战三星期,造台计算机".小G响应号召,花了三小时造了台普通计算姬.普通计算姬 ...

  3. BZOJ4765 普通计算姬

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  4. BZOJ4766: 文艺计算姬

    Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 737  Solved: 402 [Submit][Status][Discuss] Descripti ...

  5. [BZOJ4766]文艺计算姬

    [BZOJ4766]文艺计算姬 试题描述 "奋战三星期,造台计算机".小W响应号召,花了三星期造了台文艺计算姬.文艺计算姬比普通计算机有更多的艺术细胞.普通计算机能计算一个带标号完 ...

  6. Bzoj4766 文艺计算姬

    Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 234  Solved: 142 Description "奋战三星期,造台计算机" ...

  7. 省选专练之文艺计算姬

    "奋战三星期,造台计算机".小W响应号召,花了三星期造了台文艺计算姬. 文艺计算姬比普通计算机有更多的艺术细胞. 普通计算机能计算一个带标号完全图的生成树个数,而文艺计算姬能计算一 ...

  8. linux 传输大文件大小,Linux大文件传输(转)

    我们经常需要在机器之间传输文件.比如备份,复制数据等等.这个是很常见,也是很简单的.用scp或者rsync就能很好的完成任务.但是如果文件很大,需要占用一些传输时间的时候,怎样又快又好地完成任务就很重 ...

  9. ZJOI2019一轮停课刷题记录

    Preface 菜鸡HL终于狗来了他的省选停课,这次的时间很长,暂定停到一试结束,不过有机会二试的话还是可以搞到4月了 这段时间的学习就变得量大而且杂了,一般以刷薄弱的知识点和补一些新的奇怪技巧为主. ...

最新文章

  1. PyTorch训练加速17种技巧
  2. tcp/ip通信中udp头部结构udphdrp-check校验计算
  3. 计算机应用基础2004年,计算机应用基础2004年下半年全国试题参考答案2
  4. JZOJ 3814. 【NOIP2014模拟9.7】天黑黑
  5. linux内存分配堆栈数据段代码段,linux – LD_PRELOAD堆栈和数据段内存分配
  6. textview点击展开全部或收起,内容过长显示省略号,设置行间距,字间距,跑马灯显示
  7. Active Directory备份与还原
  8. 打开SQlite数据库
  9. 2021年下种子磁力最好用的网盘
  10. 分站php源码,企业网站管理系统云优CMS v2.0.5 分站版
  11. 北京林业大学计算机考研录取分数线,北京林业大学信息学院计算机技术(专业学位)专业考研招生人数 考研报录比 考研复试分数线 考研辅导.pdf...
  12. Python 生成、识别社会统一信用代码
  13. Java中grabImage_JavaCV实现将视频以帧方式抽取
  14. Linux 下配置JDK 并运行springboot项目进行访问 Tomcat的安装
  15. JAVA移动垃圾分类车管理平台计算机毕业设计Mybatis+系统+数据库+调试部署
  16. Mybatis实现联合查询(六)
  17. 数据的经济价值与个人信息安全保护,该如何平衡?
  18. 个人怎么制作微信小程序,微信小程序可以免费制作吗?微信小程序制作教程
  19. (C)problem1:C语言阶乘求和
  20. WSL2 | ROS 安装

热门文章

  1. 代码Review工具upsourse的部署
  2. 使用Wireshark工具分析网络协议
  3. Linux下的硬盘信息查看
  4. RAP2 API管理工具部署手册
  5. 神级编辑器 Vim 使用-插件篇
  6. VUE引入kindeditor、本地化、一键排版样式等操作
  7. 神经性脚臭案例整理(三)
  8. 景深--摄影基础理论(1)
  9. 《CLR via C#:框架设计》读书笔记 - 委托
  10. 什么?一个核同时执行两个线程?