题意:给一棵树,只有点权无边权, ,每次询问求以一个点为中心,半径为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. 解决Ruby在IE11中报Unable to get browser (Selenium::WebDriver::Error::NoSuchWindowError)的错误

    转载地址:http://www.tuicool.com/articles/BRnqeu2 I was updating the browser WebDrivers for    Seleno    ...

  2. 【003:ubuntu 基本开发环境设置】

    1.基础开发环境 sudo add-apt-repository ppa:webupd8team/java sudo apt-get update sudo apt-get install Oracl ...

  3. Asp.net MVC进入请求管道的过程

    Asp.net MVC进入请求管道的过程 Asp.Net MVC 跟AspNet 入口解释 Asp.Net MVC请求处理过程 mvc 请求模型 mvc的原理 mvc模型 NewMVCPipleLin ...

  4. js页面刷新之实现框架内外刷新(整体、局部)

    这次总结的是框架刷新: 框架内外的按钮均可以定义网页重定向, 框架内部页面的按钮可以实现局部刷新, 框架外部页面的按钮可以实现整页刷新. 代码如下(两个html页面): <!--主界面index ...

  5. Codeforces Round #374 (div.2)遗憾题合集

    C.Journey 读错题目了...不是无向图,结果建错图了(喵第4样例是变成无向就会有环的那种图) 并且这题因为要求路径点尽可能多 其实可以规约为限定路径长的拓扑排序,不一定要用最短路做 #prag ...

  6. python学习之认识字符串

    1.打印字符串 >>> print ("hello world") hello world 2.使用“/"进行符号转义 >>> pri ...

  7. IntelliJ IDEA使用(1)——IDEA配置JDK

    提前安装jdk,配置环境变量 一.配置jdk 1.依次点开File -->Project Structure,点击左侧标签页,点击SDKs 2.点击+号,选SDK 3.在弹出框选择jdk路径(我 ...

  8. caffe ubuntu16安装报错和程序总结

    我最近安装安装了老版本的caffe,安装过程真是两个字"想死",所以我的错误一般都是比较经典的. 我是使用cuda的版本,所以可能会出现undefined refference t ...

  9. python time模块

    time模块 (有效时间1970-2038) (1)本地时间 (2)时间戳 (3)延时 time.localtime([secs]) #struct_time time.time() #timesta ...

  10. BZOJ 2286: [Sdoi2011]消耗战

    2286: [Sdoi2011消耗战 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2082  Solved: 736[Submit][Status] ...