题意:给一棵树,只有点权无边权, ,每次询问求以一个点为中心,半径为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了,真乃神人也!

 #include<bits/stdc++.h>
using namespace std;
#define N 100005
#define INF 1e9
#define lowbit(i) ((i)&-(i))
int n,m,head[N],val[N],fa[N][],dis[N][],s[N],f[N],dep[N],rt,sz,cnt,ans;
bool vis[N];
vector<int>bit[N],fbit[N];
inline int read(){
int x=,f=; char a=getchar();
while(a>'' || a<'') {if(a=='-') f=-; a=getchar();}
while(a<='' && a>='') x=x*+a-'',a=getchar();
return x*f;
}
struct edges{
int to,next;
}e[*N];
inline void insert(){
int u=read(),v=read();
e[cnt]=(edges){v,head[u]};head[u]=cnt++;
e[cnt]=(edges){u,head[v]};head[v]=cnt++;
}
void getroot(int x,int father){
s[x]=; f[x]=;
for(int i=head[x];i>=;i=e[i].next){
if(vis[e[i].to] || father==e[i].to) continue;
getroot(e[i].to,x); s[x]+=s[e[i].to];
f[x]=max(f[x],s[e[i].to]);
}
f[x]=max(f[x],sz-s[x]);
if(f[x]<f[rt]) rt=x;
}
void getship(int x,int anc,int father,int d){
for(int i=head[x];i>=;i=e[i].next){
int v=e[i].to;
if(!vis[v] && v!=father) fa[v][++dep[v]]=anc,dis[v][dep[v]]=d,getship(v,anc,x,d+);
}
}
void Buildtree(int x){
vis[x]=; getship(x,x,,);
int all=sz; bit[x].resize(all+); fbit[x].resize(all+);
for(int i=head[x];i>=;i=e[i].next){
if(vis[e[i].to]) continue;
sz=s[e[i].to]; if(sz>s[x]) sz=all-s[x];
rt=; getroot(e[i].to,x); Buildtree(rt);
}
}
inline int qsum(int x,int k){
int ret=val[x],lim=bit[x].size()-; k=min(k,lim);
for(int i=k;i;i-=lowbit(i)) ret+=bit[x][i];
return ret;
}
inline int qsum2(int x,int k){
int ret=,lim=fbit[x].size()-; k=min(k,lim);
for(int i=k;i;i-=lowbit(i)) ret+=fbit[x][i];
return ret;
}
inline void change(int x,int v){
int d,lim;
d=dis[x][dep[x]]; lim=bit[x].size()-;
for(int j=d;j<=lim && j;j+=lowbit(j)) fbit[x][j]+=v;
for(int i=dep[x];i;i--){
d=dis[x][i]; lim=bit[fa[x][i]].size()-;
for(int j=d;j<=lim;j+=lowbit(j)) bit[fa[x][i]][j]+=v;
d=dis[x][i-];
for(int j=d;j<=lim && j;j+=lowbit(j)) fbit[fa[x][i]][j]+=v;
}
}
int query(int x,int k){
int ret=qsum(x,k);
for(int i=dep[x];i;i--) if(dis[x][i]<=k)
ret+=qsum(fa[x][i],k-dis[x][i])-qsum2(fa[x][i+],k-dis[x][i]);
return ret;
}
int main(){
n=read(); m=read(); memset(head,-,sizeof(head));
for(int i=;i<=n;i++) val[i]=read();
for(int i=;i<n;i++) insert();
f[]=INF; sz=n; getroot(,); Buildtree(rt);
for(int i=;i<=n;i++) fa[i][dep[i]+]=i;
for(int i=;i<=n;i++) change(i,val[i]);
while(m--){
int a=read(),b=read()^ans,c=read()^ans;
if(!a) ans=query(b,c),printf("%d\n",ans);
else change(b,c-val[b]),val[b]=c;
}
return ;
}

bzoj3730:震波的更多相关文章

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

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

  2. BZOJ3730 震波 和 BZOJ4372 烁烁的游戏

    "震波"题意 F.A.Qs Home Discuss ProblemSet Status Ranklist Contest 入门OJ ModifyUser  autoint Log ...

  3. bzoj3730 [震波][动态树分治+线段树+LCA]

    震波 Time Limit: 15 Sec  Memory Limit: 256 MBSubmit: 1573  Solved: 358[Submit][Status][Discuss] Descri ...

  4. bzoj千题计划244:bzoj3730: 震波

    http://www.lydsy.com/JudgeOnline/problem.php?id=3730 点分树内对每个节点动态维护2颗线段树 线段树以距离为下标,城市的价值为权值 对于节点x的两棵线 ...

  5. BZOJ3730震波——动态点分治+线段树(点分树套线段树)

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

  6. bzoj3730 震波 [动态点分治,树状数组]

    传送门 思路 如果没有强制在线的话可以离线之后CDQ分治随便搞. 有了强制在线之后--可能可以二维线段树?然而我不会算空间. 然后我们莫名其妙地想到了动态点分治,然后这题就差不多做完了. 点分树有一个 ...

  7. BZOJ3730 震波 | 动态点分治

    #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> # ...

  8. [BZOJ4372]烁烁的游戏

    题面戳我 题意: 给一颗n个节点的树,边权均为1,初始点权均为0,m次操作: Q x:询问x的点权. M x d w:将树上与节点x距离不超过d的节点的点权均加上w. \(1≤n≤10^5\) sol ...

  9. Noip前的大抱佛脚----赛前任务

    赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...

随机推荐

  1. Windows Azure Mangement API 之 更方便的使用Mangement API

    许多.Net 程序员在使用Azure Management API的时候都选择参考微软官方示例,通过创建HttpWebRequest来创建. 或者自己创建类库来封装这些API,使之调用起来更加方便. ...

  2. angularJS——自定义指令

    主要介绍指令定义的选项配置 //angular指令的定义,myDirective ,使用驼峰命名法 angular.module('myApp', []) .directive('myDirectiv ...

  3. Linux VFS中write系统调用实现原理【转】

    转自:http://blog.chinaunix.net/uid-28362602-id-3425881.html 目录 用户空间的write函数在内核里面的服务例程为sys_write Vfs_wr ...

  4. Animation小问题整理

    1.在动画播放中改变层级内容的名字,不会造成动画内容映射的改变. 2.Animator动画剪辑层级没问题,但是不播放 检查是否Mask损坏,FBX文件的Animations选项下面有个Mask.Uni ...

  5. GMF中,删除节点和连线的另一种实现

    问题 在GMF中,如果需要programmatically删除节点或连线,在google中我们很容易搜索到<GMF中,删除节点和连线的实现>一文(我并不确定这是原创作者的原始链接),很多人 ...

  6. tcp有限状态机

    a.客户端状态迁移 CLOSED->SYN_SENT->ESTABLISHED (ps:主动结束连接)->FIN_WAIT_1->FIN_WAIT_2 (如果另一方程序健壮,会 ...

  7. python virtualenv

    一  安装 pip install virtualenvwrapper - 把下面这句加到~/.bash_profile里面,如不嫌麻烦,也可以每次都手动执行.source /usr/local/bi ...

  8. file以及文件大小转化问题

    android 获取文件夹.文件的大小 以B.KB.MB.GB 为单位             public class FileSizeUtil { public static final int ...

  9. Http 状态码对照表

    1xx 消息 1. 100 Continue       2. 101 Switching Protocol       3. 102 Processing 2xx 成功 1. 200 OK      ...

  10. Python生成字体

      Python version 2.7 required, which was not found in the registry 参考:http://www.cnblogs.com/min0208 ...