LINK:duoxiao OJ LCA on Tree

题目:



一道树链剖分+树状数组的神题。

(直接nQ的暴力有50.

其实对于树随机的时候不难想到一个算法 对于x的修改 暴力修改到根.

对于儿子的答案维护 不难发现维护几个变量值即可 这样做每次是Qh的复杂度 在树随机时为logn

考虑正解:

难点还是在于修改 先把起始的答案求出来。

对于修改x x的某个孙子w答案的变化显然是 (sz[w]+1)v.

对于x的某个儿子 s来说 答案的变化为 (sz[s]+1)v+\(v\cdot \sum_{tn\in son[s]}(sz[s]-sz[tn])\)

对于x来说 答案的变化为 (sz[x]+1)v+\(v\cdot \sum_{tn\in son[x]}(sz[x]-sz[tn])(|son[tn]|+1)\)

于是对于某个点的修改来说 访问父亲 父亲的父亲被修改的权值即可。

考虑对于x的祖宗的影响。

不难发现 对于某个祖宗y来说 如果d含有x这棵子树 得到的贡献为 \((sz[y]-sz[d])\cdot C(x,2)\cdot v\)

其中C(x,2)表示和x的距离不超过2的点数。

关键是对祖宗的维护 。

一个暴力:暴力向根修改O(h).

一个暴力:求出儿子内被修改的值总和 树状数组维护dfs序 logn son[x].

不过两个暴力都不靠谱。

神技 树链剖分。

可以发现 对于第一个暴力如果我们只考虑轻链的贡献 那么这种修改最多logn次 树剖后向上跳即可。

可以发现 对于一个点来说此时其发出的所有的轻链 都被暴力跳过了。

对于重链 由于只有一条 树状数组维护求出这个重链的儿子的修改总和即可。

复杂度nlogn.非常的妙。

const int MAXN=300010;
int n,Q,len,cnt;
ui f[MAXN],a[MAXN],c[MAXN],sum[MAXN],top[MAXN],w1[MAXN],s[MAXN],w2[MAXN];
int d[MAXN],sz[MAXN],son[MAXN],dfn[MAXN],f1[MAXN],f2[MAXN];
int lin[MAXN],ver[MAXN],nex[MAXN],fa[MAXN];
inline void add(int x,int y)
{
ver[++len]=y;
nex[len]=lin[x];
lin[x]=len;
}
inline void dfs(int x,int father)
{
fa[x]=father;sz[x]=1;d[x]=d[father]+1;
sum[x]+=a[x];
go(x)
{
dfs(tn,x);
f[x]+=sz[x]*sum[tn]+sz[tn]*sum[x];
sum[x]+=sum[tn];
++f1[x];f2[x]+=f1[tn];
sz[x]+=sz[tn];
if(sz[son[x]]<sz[tn])son[x]=tn;
}
f[x]+=a[x]*2;
}
inline void dp(int x,int father)
{
top[x]=father;dfn[x]=++cnt;
if(!son[x])return;
dp(son[x],father);
go(x)if(tn!=fa[x]&&tn!=son[x])dp(tn,tn);
}
inline void dfs(int x)
{
go(x)
{
if(tn==fa[x])continue;
dfs(tn);
w1[x]+=(f1[tn]+1)*(sz[x]-sz[tn]);
w2[x]+=(sz[x]-sz[tn]);
}
}
inline void add1(int x,int y)
{
while(x<=n)
{
c[x]+=y;
x+=x&(-x);
}
return;
}
inline ui ask(int x){ui cnt=0;while(x){cnt+=c[x];x-=x&(-x);}return cnt;}
inline void change(int x,int y)
{
int s=x;y=y*(f1[x]+f2[x]+1);
add1(dfn[x],y);
while(fa[top[s]])
{
int fx=top[s];
int fw=fa[fx];
if(son[fw]!=fx)
f[fw]+=(sz[fw]-sz[fx])*y;
s=fw;
}
}
inline ui query(int x)
{
if(!son[x])return 0;
return ask(dfn[son[x]]+sz[son[x]]-1)-ask(dfn[son[x]]-1);
}
int main()
{
freopen("1.in","r",stdin);
get(n);get(Q);
rep(2,n,i){int get(x);add(x,i);}
rep(1,n,i)get(a[i]);
dfs(1,0);dp(1,1);dfs(1);
rep(1,Q,i)
{
int op,x,y;
get(op);get(x);
if(op==1)
{
get(y);
s[x]+=y;
f[x]+=(sz[x]+1+w1[x])*y;
change(x,y);
}
else
{
ui ans=f[x]+s[fa[x]]*(sz[x]+1+w2[x])+s[fa[fa[x]]]*(sz[x]+1);
ans+=query(x)*(sz[x]-sz[son[x]]);printf("%u\n",ans);
}
}
return 0;
}

4.12 省选模拟赛 LCA on tree 树链剖分 树状数组 分析答案变化量的更多相关文章

  1. 树链剖分 树剖求lca 学习笔记

    树链剖分 顾名思义,就是把一课时分成若干条链,使得它可以用数据结构(例如线段树)来维护 一些定义: 重儿子:子树最大的儿子 轻儿子:除了重儿子以外的儿子 重边:父节点与重儿子组成的边 轻边:除重边以外 ...

  2. 5.12 省选模拟赛 T2 贪心 dp 搜索 差分

    LINK:T2 这题感觉很套路 但是不会写. 区间操作 显然直接使用dp不太行 直接爆搜也不太行复杂度太高. 容易想到差分 由于使得整个序列都为0 那么第一个数也要i差分前一个数 强行加一个0 然后 ...

  3. 7.18 NOI模拟赛 树论 线段树 树链剖分 树的直径的中心 SG函数 换根

    LINK:树论 不愧是我认识的出题人 出的题就是牛掰 == 他好像不认识我 考试的时候 只会写42 还有两个subtask写挂了 拿了37 确实两个subtask合起来只有5分的好成绩 父亲能转移到自 ...

  4. FCS省选模拟赛 Day7

    Description  Solution T1 island 考虑把问题成两部分计算 纵坐标的距离和很好计算,在输入的同时一次计算了就完事 横坐标又分成两部分 分别在\(y\)轴不同侧的矩形的距离和 ...

  5. 树链剖分求LCA

    树链剖分中各种数组的作用: siz[]数组,用来保存以x为根的子树节点个数 top[]数组,用来保存当前节点的所在链的顶端节点 son[]数组,用来保存重儿子 dep[]数组,用来保存当前节点的深度 ...

  6. 树链剖分与倍增求LCA

    树链剖分与倍增求\(LCA\) 首先我要吐槽机房的辣基供电情况,我之前写了一上午,马上就要完成的时候突然停电,然后\(GG\)成了送链剖分 其次,我没歧视\(tarjan LCA\) 1.倍增求\(L ...

  7. 【洛谷比赛】[LnOI2019]长脖子鹿省选模拟赛 T1 题解

    今天是[LnOI2019]长脖子鹿省选模拟赛的时间,小编表示考的不怎么样,改了半天也只会改第一题,那也先呈上题解吧. T1:P5248 [LnOI2019SP]快速多项式变换(FPT) 一看这题就很手 ...

  8. [NOIP10.6模拟赛]2.equation题解--DFS序+线段树

    题目链接: 咕 闲扯: 终于在集训中敲出正解(虽然与正解不完全相同),开心QAQ 首先比较巧,这题是\(Ebola\)出的一场模拟赛的一道题的树上强化版,当时还口胡出了那题的题解 然而考场上只得了86 ...

  9. jzoj4918. 【GDOI2017模拟12.9】最近公共祖先 (树链剖分+线段树)

    题面 题解 首先,点变黑的过程是不可逆的,黑化了就再也洗不白了 其次,对于\(v\)的祖先\(rt\),\(rt\)能用来更新答案当且仅当\(sz_{rt}>sz_{x}\),其中\(sz\)表 ...

随机推荐

  1. Uni-app实战项目注意事项

    注意: (1)本地开启端口 App running at: Local: http://localhost:8080/ Network: http://192.168.31.43:8080/ 后台人员 ...

  2. Python——格式化GMT时间

    1.背景 最近在做视频上传去获取大小.时间的功能,视频是存在金山云的,由于金山sdk接口用例执行后返回的结果中的时间是http头部时间,时间格式为‘Tue, 08 May 2018 06:17:00 ...

  3. 显示IP地址的命令

    显示IP地址的命令   Centos7默认显示IP地址的命令       #获取所有网卡的IP地址 [root@clf ~]# ip  a1: lo: <LOOPBACK,UP,LOWER_UP ...

  4. postman-3-请求

    请求头 单击Headers选项卡将显示请求头键-值编辑器.我们可以将任何字符串设置为请求头名称.在输入字段时,自动完成下拉菜单将补充常见HTTP请求头. Content-Type标题的值也可从自动完成 ...

  5. Python 读取Excel之xlrd篇

    上一期给大家分享了如何用Python读取文本,这次给大家分享如何读取Excel表格内容,拿最常见的.xlsx和.xls格式来讲解. 本章主要知识点有: 读取整篇excel返回list[list[lis ...

  6. 数据载入、存储及文件格式知识图谱-《利用Python进行数据分析》

    所有内容整理自<利用Python进行数据分析>,使用MindMaster Pro 7.3制作,emmx格式,源文件已经上传Github,需要的同学转左上角自行下载或者右击保存图片.

  7. 并发编程之synchronized锁(一)

    一.设计同步器的意义 多线程编程中,有可能会出现多个线程同时访问同一个共享.可变资源的情况,这个资源我们称之其为临界资源:这种资源可能是:对象.变量.文件等. 共享:资源可以由多个线程同时访问 可变: ...

  8. PHP基础:(常量变量,数据类型,类型转换)

    预定义变量(系统变量) $_GET:get方式提交的数据 $_POST:post方式提交的数据 $_REQUEST:$_GET,$_POST数据综合 $GLOBALS:PHP中所有的全局变量 $_SE ...

  9. 改造 layui 表格组件实现多重排序

    layui 的表格组件目前只支持单列排序,在实际应用中并不能很好的支撑我们的业务需求.今天一时手痒,决定改造一番以支持多重排序. 实现思路也比较简单,只需要用一个数组来存放所有排序的列,再把这个数组传 ...

  10. antd踩坑:value.locale is not a function

    这个问题来源于日期选择器 RangerPicker 的特殊情况. <Col span={7} key={9}> <FormItem label="投运时间" {. ...