HDU - 5571 :tree (动态点分治 异或)
题意:给定一棵树,有点权a[],有边权。 现在有M次修改点权的操作,输出每次修改后,Σ(a[i]^a[j])*dis(i,j);
思路:因为待修改,我们需要快速得到以及修改一个点到其他所有点的信息。 肯定就是动态点分治了啊。
而异或这个操作没有什么累加的性质,所以每一位拆开单独计算。 根据二进制位置和01区别,先建立14*2点分树。然后每次在同一位置,不同值的树上累加答案。
因为计算dis的过程会重复很多次,所以可以用个dd数组,减少重复统计,然后就用1400ms变成 了960ms。
#include<bits/stdc++.h>
#define FOR() for(int i=Laxt[u];i;i=Next[i])
#define ll long long
#define rep(i,w,v) for(int i=w;i<=v;i++)
using namespace std;
const int maxn=;
int Laxt[maxn],Next[maxn<<],To[maxn<<],Len[maxn<<],cnt;
int a[maxn],sz[maxn],son[maxn],dep[maxn];
int Top[maxn],fa[maxn],Fa[maxn],vis[maxn],root,SZ;
ll G[maxn][][],F[maxn][][],ans,dis[maxn]; //
int num[maxn][][],mx;
void init(int N)
{
cnt=; rep(i,,N) Laxt[i]=;
rep(i,,N) vis[i]=; ans=;
rep(i,,N) rep(j,,) rep(k,,)
G[i][j][k]=F[i][j][k]=num[i][j][k]=;
}
void add(int u,int v,int len)
{
Next[++cnt]=Laxt[u]; Laxt[u]=cnt; To[cnt]=v; Len[cnt]=len;
}
void dfs1(int u,int f)
{
sz[u]=; dep[u]=dep[f]+; fa[u]=f; son[u]=;
for(int i=Laxt[u];i;i=Next[i]){
int v=To[i]; if(v==f) continue;
dis[v]=dis[u]+Len[i];
dfs1(v,u); sz[u]+=sz[v];
if(sz[son[u]]<sz[v]) son[u]=v;
}
}
void dfs2(int u,int tp)
{
Top[u]=tp;
if(son[u]) dfs2(son[u],tp);
FOR()
if(To[i]!=fa[u]&&To[i]!=son[u])
dfs2(To[i],To[i]);
} int LCA(int u,int v)
{
while(Top[u]^Top[v]) dep[Top[u]]<dep[Top[v]]?v=fa[Top[v]]:u=fa[Top[u]];
return dep[u]<dep[v]?u:v;
}
ll getdis(int u,int v){return dis[u]+dis[v]-*dis[LCA(u,v)];}
void Getroot(int u,int ff)
{
sz[u]=;int ret=;
FOR(){
int v=To[i];if(v==ff||vis[v])continue;
Getroot(v,u);sz[u]+=sz[v];
ret=max(ret,sz[v]);
}
ret=max(ret,SZ-sz[u]);
if(ret<mx) mx=ret,root=u;
}
void DFS(int u,int ff)
{
vis[u]=true; Fa[u]=ff;
FOR(){
int v=To[i];if(vis[v])continue;
mx=SZ=sz[v];
Getroot(v,u);
DFS(root,u);
}
}
ll dd[maxn];
void Modify(int u,int val,int opt)
{
int t;
for(int j=u;Fa[j];j=Fa[j]) dd[j]=getdis(u,Fa[j]);
rep(i,,){
if(val&(<<i)) t=;
else t=;
ans=ans+1LL*opt*(<<i)*G[u][i][t^];
for(int j=u;Fa[j];j=Fa[j]){
ll d=dd[j];
ans=ans+1LL*opt*(<<i)*(1LL*d*(num[Fa[j]][i][t^]-num[j][i][t^])+G[Fa[j]][i][t^]-F[j][i][t^]);
}
}
rep(i,,){
if(val&(<<i)) t=;
else t=;
num[u][i][t]+=opt;
for(int j=u;Fa[j];j=Fa[j]){
ll d=dd[j];
G[Fa[j]][i][t]+=d*opt;
F[j][i][t]+=d*opt;
num[Fa[j]][i][t]+=opt;
}
}
}
int main()
{
int N,Q,D,E,u,v,l;
while(~scanf("%d",&N)){
init(N);
rep(i,,N) scanf("%d",&a[i]);
rep(i,,N-){
scanf("%d%d%d",&u,&v,&l);
add(u,v,l); add(v,u,l);
}
dfs1(,); dfs2(,);
SZ=mx=N; Getroot(,);
DFS(root,);
rep(i,,N) Modify(i,a[i],);
scanf("%d",&Q);
while(Q--){
scanf("%d%d",&D,&E);
Modify(D,a[D],-);
a[D]=E;
Modify(D,a[D],);
printf("%lld\n",ans);
}
}
return ;
}
HDU - 5571 :tree (动态点分治 异或)的更多相关文章
- hdu 5909 Tree Cutting——点分治(树形DP转为序列DP)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909 点分治的话,每次要做一次树形DP:但时间应该是 siz*m2 的.可以用 FWT 变成 siz*ml ...
- hdu 5909 Tree Cutting —— 点分治
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5909 点分治,每次的 rt 是必选的点: 考虑必须选根的一个连通块,可以DP,决策就是在每个子树中决定选不 ...
- hdu 4670 Cube number on a tree(点分治)
Cube number on a tree Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/ ...
- HDU 4918 Query on the subtree(动态点分治+树状数组)
题意 给定一棵 \(n\) 个节点的树,每个节点有点权.完成 \(q\) 个操作--操作分两种:修改点 \(x\) 的点权.查询与 \(x\) 距离小于等于 \(d\) 的权值总和. \(1 \leq ...
- 【BZOJ-3730】震波 动态点分治 + 树状数组
3730: 震波 Time Limit: 15 Sec Memory Limit: 256 MBSubmit: 626 Solved: 149[Submit][Status][Discuss] D ...
- hdu 5909 Tree Cutting [树形DP fwt]
hdu 5909 Tree Cutting 题意:一颗无根树,每个点有权值,连通子树的权值为异或和,求异或和为[0,m)的方案数 \(f[i][j]\)表示子树i中经过i的连通子树异或和为j的方案数 ...
- BZOJ3435[Wc2014]紫荆花之恋——动态点分治(替罪羊式点分树套替罪羊树)
题目描述 强强和萌萌是一对好朋友.有一天他们在外面闲逛,突然看到前方有一棵紫荆树.这已经是紫荆花飞舞的季节了,无数的花瓣以肉眼可见的速度从紫荆树上长了出来.仔细看看的话,这个大树实际上是一个带权树.每 ...
- 点分治&动态点分治小结
(写篇博客证明自己还活着×2) 转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/8006488.html 有的时候,我们会发现这样一类题:它长得很像一个$O(n) ...
- 点分治&&动态点分治学习笔记
突然发现网上关于点分和动态点分的教程好像很少……蒟蒻开篇blog记录一下吧……因为这是个大傻逼,可能有很多地方写错,欢迎在下面提出 参考文献:https://www.cnblogs.com/LadyL ...
随机推荐
- 【jquery】【ztree】节点添加自定义按钮、编辑和删除事件改成自己定义事件
setting添加 edit: { drag: { isCopy: false, isMove: true }, enable: true,//设置是否处于编辑状态 showRemoveBtn: sh ...
- [转帖]Java中重写和重载与多态的关系
Java中重写和重载与多态的关系 2019-09-05 00:57:41 留下一天今天 阅读数 67 收藏 更多 分类专栏: java进阶之路 版权声明:本文为博主原创文章,遵循CC 4.0 B ...
- Go语言【学习】defer和逃逸分析
defer 什么是defer? defer是Go语言的一中用于注册延迟调用的机制,使得函数活语句可以再当前函数执行完毕后执行 为什么需要defer? Go语言提供的语法糖,减少资源泄漏的发生 如何使用 ...
- Go基础编程实践(三)—— 日期和时间
日期和时间 package main import ( "fmt" "time" ) func main() { // 获取当前时间 current := ti ...
- 【1】【leetcode-115 动态规划】 不同的子序列
给定一个字符串 S 和一个字符串 T,计算在 S 的子序列中 T 出现的个数. 一个字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串.(例如," ...
- 【leetcode-62,63,64 动态规划】 不同路径,最小路径和
给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 示例: 输入: [ [1,3,1], [1,5,1] ...
- Zipkin存储Sleuth信息实现调用链追踪的几种方法
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/alva_xu/article/detail ...
- Huber Loss 介绍
Huber Loss 是一个用于回归问题的带参损失函数, 优点是能增强平方误差损失函数(MSE, mean square error)对离群点的鲁棒性. 当预测偏差小于 δ 时,它采用平方误差,当预测 ...
- C# vb .net实现大小调整特效滤镜
在.net中,如何简单快捷地实现Photoshop滤镜组中的大小调整效果呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第 ...
- 使用@Async注解创建多线程,自定义线程池
说明 使用@Async注解创建多线程非常的方便,还可以通过配置,实现线程池.比直接使用线程池简单太多.而且在使用上跟普通方法没什么区别,加上个@Async注解即可实现异步调用. 用法 AsyncTas ...