[LNOI2014]LCA(树链剖分)
题目:给你一棵树,给你n个询问,每个询问要求输出$\sum_{i=l}^{r}depth(LCA(i,z))$
细看看其实没有想象的那么难
大体思路:
1、对于每个询问,考虑打差分变成$\sum_{i=0}^{r}depth(LCA(i,z))-\sum_{i=0}^{l-1}depth(LCA(i,z))$
2、那么这里就是一个思考点了
如何表示$\sum_{i=0}^{p}depth(LCA(i,z))$?
我也不知道
这种时候就该换一个角度思考了
啥是深度?
不就是从根到他有几个点嘛
对于两个点i,j
从i向根的路径上+1
那么$query(root,j)$就是要求的$dep(LCA(i,j))$了
到这里思路就差不多出来了
①把每个询问分成两个,打差分
②排序询问,逐个插入$add(i,root,1)$
③每个询问查出$query(z,root)$
好了答案出来了
#include<cstdio>
#include<algorithm>
using std::sort;
#define mo 201314
)%mo;}
int n,m;
struct sumireko
{
int to,ne;
}e[];
],ecnt;
void addline(int f,int t)
{
e[++ecnt].to=t;
e[ecnt].ne=he[f];
he[f]=ecnt;
}
],hop[],size[],dson[],llen[],dep[],idn[],idnar;
void dfs1(int x)
{
size[x]=;
;
for(int i=he[x],t;i;i=e[i].ne)
{
t=e[i].to;
dfs1(t);
size[x]+=size[t];
if(lin<size[t])
{
lin=size[t];
dson[x]=t;
}
}
}
void dfs2(int x,int top)
{
idn[x]=++idnar;
hop[x]=top;
llen[top]++;
if(!dson[x]) return;
dfs2(dson[x],top);
for(int i=he[x],t;i;i=e[i].ne)
{
t=e[i].to;
if(t==dson[x]) continue;
dfs2(t,t);
}
}
struct usami
{
int f,id,r,z;
void set(int u,int i,int o,int p){f=u,id=i,r=o,z=p;}
bool friend operator < (usami a,usami b)
{
return a.r<b.r;
}
}qqq[];
int qcnt;
];
struct segtree
{
],del[],size[];
void build(int px,int pl,int pr)
{
if(pl==pr)
{
size[px]=;
return;
}
;
build(px<<,pl,mid);
build(px<<|,mid+,pr);
size[px]=size[px<<]+size[px<<|];
}
void fuckup(int px,int pl,int pr)
{
if(pl==pr) return;
v[px]=v[px<<]+v[px<<|];
MOD(v[px]);
}
void fuckdown(int px,int pl,int pr)
{
if(pl==pr) return;
if(del[px])
{
v[px<<]+=del[px]*size[px<<];MOD(v[px<<]);
del[px<<]+=del[px];MOD(del[px<<]);
v[px<<|]+=del[px]*size[px<<|];MOD(v[px<<|]);
del[px<<|]+=del[px];MOD(del[px<<|]);
del[px]=;
}
}
void add(int px,int pl,int pr,int vin,int ql,int qr)
{
if(ql<=pl&&qr>=pr)
{
v[px]+=vin*size[px];
del[px]+=vin;
MOD(v[px]);
MOD(del[px]);
return;
}
fuckdown(px,pl,pr);
;
,pl,mid,vin,ql,qr);
|,mid+,pr,vin,ql,qr);
fuckup(px,pl,pr);
}
int query(int px,int pl,int pr,int ql,int qr)
{
if(ql<=pl&&qr>=pr) return v[px];
fuckdown(px,pl,pr);
;
;
,pl,mid,ql,qr),MOD(ret);
|,mid+,pr,ql,qr),MOD(ret);
return ret;
}
}tr;
void inp(int x)
{
])
{
tr.add(,,n,,idn[hop[x]],idn[x]);
x=fa[hop[x]];
}
tr.add(,,n,,idn[],idn[x]);
}
void qq(int x,int id,int f)
{
;
])
{
prt+=tr.query(,,n,idn[hop[x]],idn[x]);
MOD(prt);
x=fa[hop[x]];
}
prt+=tr.query(,,n,idn[],idn[x]);
MOD(prt);
ans[id]+=f*prt;
MOD(ans[id]);
}
int main()
{
scanf("%d%d",&n,&m);
;i<n;i++) scanf("%d",&fa[i]),addline(fa[i],i);
dep[]=;
dfs1();
dfs2(,);
tr.build(,,n);
,lin,rin,zin;i<=m;i++)
{
scanf("%d%d%d",&lin,&rin,&zin);
qqq[++qcnt].,i,lin-,zin);
qqq[++qcnt].,i,rin,zin);
}
sort(qqq+,qqq+qcnt+);
;
;i<=qcnt;i++)
{
while(tinar<qqq[i].r) {tinar++;inp(tinar);}
qq(qqq[i].z,qqq[i].id,qqq[i].f);
}
;i<=m;i++)
printf("%d\n",ans[i]);
;
}
精污代码慎入
[LNOI2014]LCA(树链剖分)的更多相关文章
- [BZOJ3626] [LNOI2014]LCA(树链剖分)
[BZOJ3626] [LNOI2014]LCA(树链剖分) 题面 给出一棵N个点的树,要求支持Q次询问,每次询问一个点z与编号为区间[l,r]内的点分别求最近公共祖先得到的最近公共祖先深度和.N, ...
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
- BZOJ 3626: [LNOI2014]LCA( 树链剖分 + 离线 )
说多了都是泪啊...调了这么久.. 离线可以搞 , 树链剖分就OK了... -------------------------------------------------------------- ...
- BZOJ3626[LNOI2014]LCA——树链剖分+线段树
题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...
- bzoj 3626 : [LNOI2014]LCA (树链剖分+线段树)
Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q ...
- 【bzoj3626】[LNOI2014]LCA 树链剖分+线段树
题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...
- BZOJ 3626: [LNOI2014]LCA 树链剖分 线段树 离线
http://www.lydsy.com/JudgeOnline/problem.php?id=3626 LNOI的树链剖分题没有HAOI那么水,学到的东西还是很多的. 我如果现场写,很难想出来这种题 ...
- BZOJ 3626 [LNOI2014]LCA ——树链剖分
思路转化很巧妙. 首先把询问做差分. 然后发现加入一个点就把路径上的点都+1,询问的时候直接询问到根的路径和. 这样和原问题是等价的,然后树链剖分+线段树就可以做了. #include <map ...
- bzoj3626 [LNOI2014]LCA——树链剖分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3626 思路很巧妙,把区间换成前缀和相减: 把 l ~ r 到根路径上的点的点权都+1,然后 ...
- 洛谷 P4211 [LNOI2014]LCA (树链剖分+离线)
题目:https://www.luogu.org/problemnew/solution/P4211 相当难的一道题,其思想难以用言语表达透彻. 对于每个查询,区间[L,R]中的每个点与z的lca肯定 ...
随机推荐
- linux常见基础问题
1,32位与64位的区别,怎么查看系统版本? 32位相比于64位处理速度更慢一些,64位同样也比32位更占内存.用户体验上没有区别:用uname -a 查看系统版本信息 2,swap分区的作用是什么 ...
- 利用JFreeChart生成时序图(6) (转自 JSP开发技术大全)
利用JFreeChart生成时序图(6) (转自 JSP开发技术大全) 14.6 利用JFreeChart生成时序图 通过JFreeChart插件只能生成普通效果的时序图,利用工厂类ChartFact ...
- poj 2762(tarjan缩点+判断是否是单链)
Going from u to v or from v to u? Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 19234 ...
- Excel设定编辑列权限的方法
工具---保护--允许用户编辑区域 --新建-- 选择(或输入)引用单元格 ,区域密码:对不同的人不同的区域用不同的密码,设置完成后,保护工作表(密码用管理员的),即可
- mybaties中,模糊查询的几种写法
模糊查询: 工作中用到,写三种用法吧,第四种为大小写匹配查询 1. sql中字符串拼接 SELECT * FROM tableName WHERE name LIKE CONCAT(CONCAT('% ...
- MySql 5.7 Archive 版本安装失败 解决过程
下载地址 https://dev.mysql.com/downloads/mysql/5.7.html#downloads 按照网络教程: 创建my.ini 文件,并填写配置内容: [mysql] # ...
- 两个局域网(办公网-IDC)安全互通方案2:by GRE and linux server&深入理解GRE
(0)gre的turnel的打通 1. 这个过程就是双方建立turnel的过程. (1)局域网路由过程 1.主机A发送一个源为192.168.1.2,目的为10.1.1.2的包 ( ...
- 0629-TP整理四(create(),success(),error(),U())
create()-前提:表单中name的值要与数据库中的字段一一匹配 可直接获取表单数据进行操作: 作用:将数据库中没有的字段在数组中去除. PHP中添加的语法如下: success()和error( ...
- bzoj 1778: [Usaco2010 Hol]Dotp 驱逐猪猡【dp+高斯消元】
算是比较经典的高斯消元应用了 设f[i]为i点答案,那么dp转移为f[u]=Σf[v]*(1-p/q)/d[v],意思是在u点爆炸可以从与u相连的v点转移过来 然后因为所有f都是未知数,高斯消元即可( ...
- bzoj 1633: [Usaco2007 Feb]The Cow Lexicon 牛的词典【dp】
预处理出g[i][j]表示原串第i个匹配第j个单词需要去掉几个字母(匹配不上为-1) 设f[i]为i及之后满足条件要去掉的最少字母 倒着dp! f[i]初始为f[i+1]+1,转移方程为f[i]=mi ...