题意:给一棵树,只有点权无边权, ,每次询问求以一个点为中心,半径为k的全职和。

考虑动态树分治。我们对于每个点(点分树)维护两个树状数组。两个树状数组都以距离为下标,权值为内容。第一个树状数组维护子树中距离该点为k的权值和,第二个维护距离该点父亲距离为k的权值和。这样改权值时我们暴力爬树高,loglog复杂度(log的树高加上log的树状数组)。查询的时候一样爬树高,要注意容斥(把当前子树k的先加起来,往祖先上爬,如果距离小于k,假设为d,我们到祖先上去求一个k-d,再容斥掉原来这棵子树里被计算过的,这就是第二个树状数组的用处)。

时间复杂度0(nloglog),空间复杂度O(nlog)(如果用线段树还要加一个log。这里BB一句,为什么树状数组不会爆呢,因为你每一层开的大小为子树大小的话,每层总和n,总共log层,空间就是nlog的。其实就跟点分治的时间复杂度证明一样。用vector来开并且加上函数resize()就可以办到了。)

这道题花了整整一天才写出来。。。一直RE(实际是WA,毕竟防离线加密,如果答案错了后面输入都是错的),总结一下错误:

1.想的只用一个树状数组维护,实际上为了容斥必须要用上第二个树状数组。

2.更新时,一开始要把自己丢在自己的第二个树状数组里面

3.2这玩意肯定要写在爬树循环外面啊(你是SB吗)

4.应该用qsum而不是query去爬树高(一开始脑袋抽了。。)

5.往树上爬的时候是不会中途退出的,不会因为有一个祖先爬不上去就终止,说不定有一个爷爷就在你旁边你可以过去呢。

对于点分树的题就想象成爬山吧,我们用每一层的重心将点们分割开来,每次爬树高都是解锁区域,翻过一座高山。

还有,点分树自己脑补的板子实在太丑陋了。。这里膜拜一下ihopenot大佬,板子神快,我一开始好不容易调出来T了,参考了一下大佬的板子后就rank8了,真乃神人也!

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 100005
 4 #define INF 1e9
 5 #define lowbit(i) ((i)&-(i))
 6 int n,m,head[N],val[N],fa[N][20],dis[N][20],s[N],f[N],dep[N],rt,sz,cnt,ans;
 7 bool vis[N];
 8 vector<int>bit[N],fbit[N];
 9 inline int read(){
10     int x=0,f=1; char a=getchar();
11     while(a>'9' || a<'0') {if(a=='-') f=-1; a=getchar();}
12     while(a<='9' && a>='0') x=x*10+a-'0',a=getchar();
13     return x*f;
14 }
15 struct edges{
16     int to,next;
17 }e[2*N];
18 inline void insert(){
19     int u=read(),v=read();
20     e[cnt]=(edges){v,head[u]};head[u]=cnt++;
21     e[cnt]=(edges){u,head[v]};head[v]=cnt++;
22 }
23 void getroot(int x,int father){
24     s[x]=1; f[x]=0;
25     for(int i=head[x];i>=0;i=e[i].next){
26         if(vis[e[i].to] || father==e[i].to) continue;
27         getroot(e[i].to,x); s[x]+=s[e[i].to];
28         f[x]=max(f[x],s[e[i].to]);
29     }
30     f[x]=max(f[x],sz-s[x]);
31     if(f[x]<f[rt]) rt=x;
32 }
33 void getship(int x,int anc,int father,int d){
34     for(int i=head[x];i>=0;i=e[i].next){
35      int v=e[i].to;
36      if(!vis[v] && v!=father) fa[v][++dep[v]]=anc,dis[v][dep[v]]=d,getship(v,anc,x,d+1);
37     }
38 }
39 void Buildtree(int x){
40     vis[x]=1; getship(x,x,0,1);
41     int all=sz; bit[x].resize(all+1); fbit[x].resize(all+1);
42     for(int i=head[x];i>=0;i=e[i].next){
43         if(vis[e[i].to]) continue;
44         sz=s[e[i].to]; if(sz>s[x]) sz=all-s[x];
45         rt=0; getroot(e[i].to,x); Buildtree(rt);
46     }
47 }
48 inline int qsum(int x,int k){
49     int ret=val[x],lim=bit[x].size()-1; k=min(k,lim);
50     for(int i=k;i;i-=lowbit(i)) ret+=bit[x][i];
51     return ret;
52 }
53 inline int qsum2(int x,int k){
54     int ret=0,lim=fbit[x].size()-1; k=min(k,lim);
55     for(int i=k;i;i-=lowbit(i)) ret+=fbit[x][i];
56     return ret;
57 }
58 inline void change(int x,int v){
59     int d,lim;
60     d=dis[x][dep[x]]; lim=bit[x].size()-1;
61     for(int j=d;j<=lim && j;j+=lowbit(j)) fbit[x][j]+=v;
62     for(int i=dep[x];i;i--){
63         d=dis[x][i]; lim=bit[fa[x][i]].size()-1;
64         for(int j=d;j<=lim;j+=lowbit(j)) bit[fa[x][i]][j]+=v;
65         d=dis[x][i-1];
66         for(int j=d;j<=lim && j;j+=lowbit(j)) fbit[fa[x][i]][j]+=v;
67     }
68 }
69 int query(int x,int k){
70     int ret=qsum(x,k);
71     for(int i=dep[x];i;i--) if(dis[x][i]<=k)
72     ret+=qsum(fa[x][i],k-dis[x][i])-qsum2(fa[x][i+1],k-dis[x][i]);
73     return ret;
74 }
75 int main(){
76     n=read(); m=read(); memset(head,-1,sizeof(head));
77     for(int i=1;i<=n;i++) val[i]=read();
78     for(int i=1;i<n;i++) insert();
79     f[0]=INF; sz=n; getroot(1,0); Buildtree(rt);
80     for(int i=1;i<=n;i++) fa[i][dep[i]+1]=i;
81     for(int i=1;i<=n;i++) change(i,val[i]);
82     while(m--){
83         int a=read(),b=read()^ans,c=read()^ans;
84         if(!a) ans=query(b,c),printf("%d\n",ans);
85         else change(b,c-val[b]),val[b]=c;
86     }
87     return 0;
88 }

转载于:https://www.cnblogs.com/enigma-aw/p/6209545.html

bzoj3730:震波相关推荐

  1. BZOJ3730 震波 【动态点分治】*

    BZOJ3730 震波 Description 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]. 不幸的是,这片土 ...

  2. [BZOJ3730]震波(动态点分治)

    3730: 震波 Time Limit: 15 Sec  Memory Limit: 256 MB Submit: 2260  Solved: 470 [Submit][Status][Discuss ...

  3. BZOJ3730 震波+BZOJ4372 烁烁的游戏(动态点分治)

    震波 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]. 不幸的是,这片土地常常发生地震,并且随着时代的发展,城市的 ...

  4. [BZOJ3730]震波-动态点分治

    震波 Description 在一片土地上有N个城市,通过N-1条无向边互相连接,形成一棵树的结构,相邻两个城市的距离为1,其中第i个城市的价值为value[i]. 不幸的是,这片土地常常发生地震,并 ...

  5. Bzoj3730 震波

    Time Limit: 15 Sec  Memory Limit: 256 MB Submit: 753  Solved: 176 Description 在一片土地上有N个城市,通过N-1条无向边互 ...

  6. Bzoj3730: 震波

    题面 戳我 Sol 动态点分治: 建个点分树,每个节点开两颗线段树,以与该点的距离为下标,维护价值和 一棵树维护这个点的,一棵维护对上层重心的贡献 然后.. 然后?直接暴力搞就行了 注意常数优化我TL ...

  7. bzoj3730震波

    这是一道动态点分治好题. 在点分树上,对于每个点,维护两个树状数组,一个维护离点分中心距离不超过某个值的点权和,另一个维护离点分中心的父亲距离不超过某个值的点权和.注意树状数组的大小不必开到联通子树的 ...

  8. [BZOJ3730]震波

    题目   点这里看题目.    BZOJ 目测-是炸了. 分析   动态点分治入门题.   首先理解什么叫 " 动态点分治 ".   一般点分治需要离线解决,不带修改.动态点分治可 ...

  9. bzoj3730. 震波

    动态点分治 考虑从每一个"块"里找到距离k范围内的点的和 为了去重, 每个x维护两个线段树:(都是关于自己分治树子树的点) 1.下标为距离x的距离,权值为val的 2.下标为距离x ...

  10. BZOJ3730 震波 【动态点分治】

    传送门 SOL 点分树模板 细节看注释吧 多写几遍应该就好了 CODE #include<bits/stdc++.h> using namespace std; #define sf sc ...

最新文章

  1. win7 桌面右下角音量图标消失的解决办法 参考
  2. php 打印对象详细信息,php打印显示数组与对象的函数详解
  3. 互联网公司忽悠员工的黑话,套路太深了。。
  4. android studio 应用全屏页,Android开发之设置应用设置全屏的两种解决方法 兼容android5.0等两种解决方法...
  5. mysql limti_MYSQL分页 limint
  6. Java开源框架 iBase4J 搭建笔记
  7. 图解110配线架打线方法
  8. HIT CSAPP大作业--程序人生
  9. 详解AD(Altium Designer)中的机械层 - 2
  10. 解决WIN10“系统和压缩内存”“ntoskrnl.exe”系统空闲时占用大量CPU
  11. Go是Google的语言,而不是我们的语言
  12. IDEA 数组遍历快捷键
  13. Python实现文件夹复制操作
  14. 百度传课网易云课堂在线教育平台竞品分析【转】
  15. “用指定的用户名和密码无法登录到该ftp服务器”解决办法
  16. 马拉松成绩和体重的关系
  17. 棋盘问题 51Nod - 1605
  18. CSDN推荐好书:《软件开发的科学与艺术》
  19. axios(三)- 源码
  20. python sequence_干货来袭!Python高阶函数使用总结~

热门文章

  1. HTML DOM selectedIndex 属性
  2. 全球与中国海藻DHA市场深度研究分析报告
  3. php 中大括号,PHP中大括号的作用总结
  4. 打开网页 doctype html,HTML: !DOCTYPE 声明
  5. 10.面向对象分析OOA笔记
  6. 马光远:当前房地产产能严重过剩 80%开发商将倒闭
  7. 同一台机器,不同服务,不同JDK,如何巧妙配置各自JDK启动
  8. 花季那年北漂(茫茫然)
  9. SQL查询语句执行顺序详解
  10. D3D还是GDI? Windows平台播放RTSP或RTMP渲染模式比较