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 ...
随机推荐
- spark笔记 环境配置
spark笔记 spark简介 saprk 有六个核心组件: SparkCore.SparkSQL.SparkStreaming.StructedStreaming.MLlib,Graphx Spar ...
- [精] UBOOT2017+FIT 启动流程详尽分析
开发环境:Nanopi-neo-plus2 软件版本:uboot-2017 软件版本:linux-4.14 买这个板子有一段时间了,并没有全身心的投入在上面,有时间了的话就搞一搞, 这篇随笔算是对这个 ...
- CF-Educational Codeforces Round 77 (Rated for Div. 2)(A-E题解)
A. Heating (水题) 题目链接 大致思路: 因为是代价是平方,所以让每一个房间的大小平均即可,即最大和最小相差不超过一. 代码: #include<bits/stdc++.h> ...
- Delphi编码与签名【URL编码与解码,Base64编码与解码,MD5加密,HMAC-SHA1、HMAC-SHA224、HMAC-SHA256、HMAC-SHA384和HMAC-SHA512签名】
作者QQ:(648437169) 点击下载➨delphi编码与签名 [Delphi编码与签名]URL编码与解码,Base64编码与解码,MD5加密,HMAC-SHA1.HMAC-SHA224.HMAC ...
- Tkint中Label&Button&Scale的使用
top.geometry()设定窗口的初始大小 scale.set()设定滑块的初始值 scale.get()获取滑块变化的值 控件通过回调函数与其他控件进行通信(Label控件中的文本会受到Scal ...
- *** WARNING L16: UNCALLED SEGMENT, IGNORED FOR OVERLAY PROCESS
Warning提示的原因是 一些未使用的函数被编译进入芯片,浪费了RAM/ROM. 解决的方法: 1.将不用的函数注释: 2.在未使用函数的首尾加条件编译 #ifdef 函数名 和 #endif ,不 ...
- Spring Boot Freemarker特别篇之contextPath【从零开始学Spring Boot
需求缘起:有人在群里@我:请教群主大神一个问题,spring boot + freemarker 怎么获取contextPath 头疼死我了,网上没一个靠谱的 .我就看看之前博客中的 [Spri ...
- ADO.net(内置类区别)随记
Ado.net使用流程 SqlConnection->open->SqlCommand(sqlstring,conn)->(ExcuteNonQuery \ExecuteScalar ...
- [Linux学习--用户管理]centos中添加一个新用户,并授权
前言 有时候给root用户不太方便,新建一个用于并赋予权限这个做法相对好些 创建新用户 创建一个用户名为:cmj [root@localhost ~]# adduser cmj 为这个用户初始化密码, ...
- git安装用法和常用命令
目录 git 下载 安装 git 工作中常用命令 Git常用命令汇总以及其它相关操作 或者 常出错误: 常用修改: 题外话(相关概念) git 下载 安装 1.下载Git,官网地址:https://g ...