热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【bzoj3730:震波】【动态树分治】

题意给出一棵树,点有点权,每次询问距离一个点不超过kkk的点的点权和,或者修改一个点的点权,强制在线。n≤100000n\

题意

给出一棵树,点有点权,每次询问距离一个点不超过kkk的点的点权和,或者修改一个点的点权,强制在线。
n≤100000n\le100000n100000


分析

把点分树建出来,然后对每个分治中心用树状数组维护到该点距离为定值的点权和,以及到他点分树上父亲距离为定值的点权和。查询的时候每次沿着父亲往上跳,在计算当前点贡献时需要减去上一个点所在子树的贡献。
时间复杂度O(nlog⁡2n)O(n\log^2n)O(nlog2n)


代码

#include
#include
#include
#include
#include
#includeconst int N=100005;int n,m,cnt,last[N],dep[N],dfn[N],top,rmq[N*2][20],lg[N*2],bin[20],c1[20][N],c2[20][N],fa[N],rt,sum,mx[N],a[N],beg[N],size[N],dd[N],tot[20],end[N];
bool vis[N];
struct edge{int to,next;}e[N*2];void addedge(int u,int v)
{e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;
}void dfs(int x,int fa)
{rmq[++top][0]=x;dep[x]=dep[fa]+1;dfn[x]=top;for (int i=last[x];i;i=e[i].next)if (e[i].to!=fa) dfs(e[i].to,x),rmq[++top][0]=x;
}void get_rmq()
{for (int i&#61;1;i<&#61;top;i&#43;&#43;) lg[i]&#61;log(i)/log(2);bin[0]&#61;1;for (int i&#61;1;i<&#61;lg[top];i&#43;&#43;) bin[i]&#61;bin[i-1]*2;for (int j&#61;1;j<&#61;lg[top];j&#43;&#43;)for (int i&#61;1;i&#43;bin[j]-1<&#61;top;i&#43;&#43;)rmq[i][j]&#61;dep[rmq[i][j-1]]<dep[rmq[i&#43;bin[j-1]][j-1]]?rmq[i][j-1]:rmq[i&#43;bin[j-1]][j-1];
}int get_dis(int x,int y)
{int l&#61;std::min(dfn[x],dfn[y]),r&#61;std::max(dfn[x],dfn[y]),w&#61;lg[r-l&#43;1];return dep[x]&#43;dep[y]-2*std::min(dep[rmq[l][w]],dep[rmq[r-bin[w]&#43;1][w]]);
}void get_root(int x,int fa)
{size[x]&#61;1;mx[x]&#61;0;for (int i&#61;last[x];i;i&#61;e[i].next){if (e[i].to&#61;&#61;fa||vis[e[i].to]) continue;get_root(e[i].to,x);size[x]&#43;&#61;size[e[i].to];mx[x]&#61;std::max(mx[x],size[e[i].to]);}mx[x]&#61;std::max(mx[x],sum-size[x]);if (!rt||mx[x]<mx[rt]) rt&#61;x;
}void ins1(int d,int x,int y)
{while (x<&#61;n) c1[d][x]&#43;&#61;y,x&#43;&#61;x&(-x);
}void ins2(int d,int x,int y)
{while (x<&#61;n) c2[d][x]&#43;&#61;y,x&#43;&#61;x&(-x);
}int query1(int d,int x)
{if (!d) return 0;int ans&#61;0;while (x) ans&#43;&#61;c1[d][x],x-&#61;x&(-x);return ans;
}int query2(int d,int x)
{if (!d) return 0;int ans&#61;0;while (x) ans&#43;&#61;c2[d][x],x-&#61;x&(-x);return ans;
}void pre(int x,int fa,int p1,int p2)
{ins1(dd[p1],beg[p1]&#43;get_dis(p1,x),a[x]);if (p2) ins2(dd[p1],beg[p1]&#43;get_dis(p2,x)-1,a[x]);tot[dd[p1]]&#43;&#43;;size[x]&#61;1;for (int i&#61;last[x];i;i&#61;e[i].next)if (e[i].to!&#61;fa&&!vis[e[i].to]) pre(e[i].to,x,p1,p2),size[x]&#43;&#61;size[e[i].to];
}void solve(int x)
{vis[x]&#61;1;dd[x]&#61;dd[fa[x]]&#43;1;beg[x]&#61;tot[dd[x]]&#43;1;pre(x,0,x,fa[x]);end[x]&#61;tot[dd[x]];for (int i&#61;last[x];i;i&#61;e[i].next)if (!vis[e[i].to]){rt&#61;0;sum&#61;size[e[i].to];get_root(e[i].to,x);fa[rt]&#61;x;solve(rt);}
}int query(int x,int y)
{int ans&#61;0,ls&#61;0,now&#61;x;while (now){int d&#61;y-get_dis(x,now);if (d>&#61;0) ans&#43;&#61;query1(dd[now],std::min(beg[now]&#43;d,end[now]))-query1(dd[now],beg[now]-1);if (d>&#61;0) ans-&#61;query2(dd[ls],std::min(beg[ls]&#43;d-1,end[ls]))-query2(dd[ls],beg[ls]-1);ls&#61;now;now&#61;fa[now];}return ans;
}void modify(int x,int y)
{int del&#61;y-a[x],now&#61;x;a[x]&#61;y;while (now){ins1(dd[now],beg[now]&#43;get_dis(now,x),del);if (fa[now]) ins2(dd[now],beg[now]&#43;get_dis(fa[now],x)-1,del);now&#61;fa[now];}
}int main()
{scanf("%d%d",&n,&m);for (int i&#61;1;i<&#61;n;i&#43;&#43;) scanf("%d",&a[i]);for (int i&#61;1;i<n;i&#43;&#43;){int x,y;scanf("%d%d",&x,&y);addedge(x,y);}dfs(1,0);get_rmq();rt&#61;0;sum&#61;n;get_root(1,0);solve(rt);int ans&#61;0;while (m--){int op,x,y;scanf("%d%d%d",&op,&x,&y);x^&#61;ans;y^&#61;ans;if (!op) printf("%d\n",ans&#61;query(x,y));else modify(x,y);}return 0;
}

推荐阅读
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • 3.223.28周学习总结中的贪心作业收获及困惑
    本文是对3.223.28周学习总结中的贪心作业进行总结,作者在解题过程中参考了他人的代码,但前提是要先理解题目并有解题思路。作者分享了自己在贪心作业中的收获,同时提到了一道让他困惑的题目,即input details部分引发的疑惑。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • FeatureRequestIsyourfeaturerequestrelatedtoaproblem?Please ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文讨论了如何使用IF函数从基于有限输入列表的有限输出列表中获取输出,并提出了是否有更快/更有效的执行代码的方法。作者希望了解是否有办法缩短代码,并从自我开发的角度来看是否有更好的方法。提供的代码可以按原样工作,但作者想知道是否有更好的方法来执行这样的任务。 ... [详细]
author-avatar
JIE9118_755
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有