BZOJ 3626: [LNOI2014]LCA 树链剖分 线段树 离线
http://www.lydsy.com/JudgeOnline/problem.php?id=3626
直接引用清华爷gconeice的题解吧
显然,暴力求解的复杂度是无法承受的。
考虑这样的一种暴力,我们把 z 到根上的点全部打标记,对于 l 到 r 之间的点,向上搜索到第一个有标记的点求出它的深度统计答案。观察到,深度其实就是上面有几个已标记了的点(包括自身)。所以,我们不妨把 z 到根的路径上的点全部 +1,对于 l 到 r 之间的点询问他们到根路径上的点权和。仔细观察上面的暴力不难发现,实际上这个操作具有叠加性,且可逆。也就是说我们可以对于 l 到 r 之间的点 i,将 i 到根的路径上的点全部 +1, 转而询问 z 到根的路径上的点(包括自身)的权值和就是这个询问的答案。把询问差分下,也就是用 [1, r] ? [1, l ? 1] 来计算答案,那么现在我们就有一个明显的解法。从 0 到 n ? 1 依次插入点 i,即将 i 到根的路径上的点全部+1。离线询问答案即可。我们现在需要一个数据结构来维护路径加和路径求和,显然树链剖分或LCT 均可以完成这个任务。树链剖分的复杂度为 O((n + q)· log n · log n),LCT的复杂度为 O((n + q)· log n),均可以完成任务。至此,题目已经被我们完美解决。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=;
const long long modn=;
const long long minf=<<;
int n,m;
struct nod{
int y,next;
}e[maxn];int head[maxn]={},tot=;
int fa[maxn]={},top[maxn]={},pos[maxn]={},kid[maxn]={},dep[maxn]={};
void init(int x,int y){
e[++tot].y=y;e[tot].next=head[x];head[x]=tot;
}
int dfs1(int x){
int y,hug=,siz,tsn=;dep[x]=dep[fa[x]]+;
for(int i=head[x];i;i=e[i].next){
y=e[i].y;
if(y==fa[x])continue;
siz=dfs1(y);
if(siz>hug)hug=siz,kid[x]=y;
tsn+=siz;
}return tsn;
}
void dfs2(int x,int pa){
int y;top[x]=pa;pos[x]=++tot;
if(kid[x])dfs2(kid[x],pa);
for(int i=head[x];i;i=e[i].next){
y=e[i].y;
if(y==kid[x]||y==fa[x])continue;
dfs2(y,y);
}
}
struct seg{
long long sum,w,l,r;
seg(){sum=l=r=;}
}t[maxn*];
void build(int x,int l,int r){
t[x].l=l;t[x].r=r;
if(l==r)return;
int mid=(l+r)/;
build(x*,l,mid);
build(x*+,mid+,r);
}
void pushup(int x){
if(t[x].r>t[x].l)t[x].sum=t[x*].sum+t[x*+].sum;
t[x].sum+=(t[x].r-t[x].l+)*t[x].w;
}
void add(int x,int l,int r){
if(l<=t[x].l&&t[x].r<=r){
if(t[x].l==t[x].r)t[x].sum+=;
else {t[x].w+=;pushup(x);}
return;
}
int mid=(t[x].l+t[x].r)/,ls=x*,rs=x*+;
if(r>mid) add(rs,l,r);
if(l<=mid) add(ls,l,r);
pushup(x);
}
long long sum(int x,int l,int r,int w){
if(l<=t[x].l&&t[x].r<=r)return t[x].sum+w*(t[x].r-t[x].l+);
int mid=(t[x].l+t[x].r)/,ls=x*,rs=x*+;long long tsn=;
if(l<=mid) tsn+=sum(ls,l,r,w+t[x].w);
if(r>mid) tsn+=sum(rs,l,r,w+t[x].w);
return tsn;
}
long long doit(int x){
int a=top[x];long long tsn=;
for(;a!=;){
tsn+=sum(,pos[a],pos[x],);
x=fa[a];a=top[x];
}
tsn+=sum(,pos[a],pos[x],);
return tsn;
}
void datup(int x){
int a=top[x];
for(;a!=;){
add(,pos[a],pos[x]);
x=fa[a];a=top[x];
}
add(,pos[a],pos[x]);
}
struct lcc{
int num;
int z;int id;
long long ans;
}q[maxn*];
bool cmp1(lcc aa,lcc bb){return aa.num<bb.num;}
bool cmp2(lcc aa,lcc bb){return aa.id<bb.id;}
int main(){
scanf("%d%d",&n,&m);
int x,y,z;
for(int i=;i<n;i++){
scanf("%d",&y);
init(y+,i+);
fa[i+]=y+;
}tot=;dfs1();dfs2(,);build(,,n);tot=;
for(int j=;j<=m;j++){
scanf("%d%d%d",&x,&y,&z);
x++;y++;z++;
if(y<x)swap(x,y);
q[++tot].num=x-;q[tot].z=z;q[tot].id=tot;
q[++tot].num=y;q[tot].z=z;q[tot].id=tot;
}sort(q+,q++tot,cmp1);
int now=;
for(int i=;i<=tot;i++){
while(now<q[i].num){
now++;datup(now);
}
q[i].ans=doit(q[i].z);
}
sort(q+,q++tot,cmp2);
for(int i=;i<=m;i++){
long long z=(q[i*].ans-q[i*-].ans)%;
printf("%lld\n",z);
}
return ;
}
BZOJ 3626: [LNOI2014]LCA 树链剖分 线段树 离线的更多相关文章
- 【bzoj3626】[LNOI2014]LCA 树链剖分+线段树
题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
- BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)
前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...
- bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)
4196: [Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2852 Solved: 1668[Submit][Sta ...
- bzoj 2157: 旅游【树链剖分+线段树】
裸的树链剖分+线段树 但是要注意一个地方--我WA了好几次才发现取完相反数之后max值和min值是要交换的-- #include<iostream> #include<cstdio& ...
- BZOJ 3589 动态树 (树链剖分+线段树)
前言 众所周知,90%90\%90%的题目与解法毫无关系. 题意 有一棵有根树,两种操作.一种是子树内每一个点的权值加上一个同一个数,另一种是查询多条路径的并的点权之和. 分析 很容易看出是树链剖分+ ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- bzoj2243[SDOI2011]染色 树链剖分+线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9012 Solved: 3375[Submit][Status ...
随机推荐
- [洛谷P1029]最大公约数与最小公倍数问题 题解(辗转相除法求GCD)
[洛谷P1029]最大公约数与最小公倍数问题 Description 输入二个正整数x0,y0(2<=x0<100000,2<=y0<=1000000),求出满足下列条件的P, ...
- eclipse加速/Nginx配置跨域代理
下班时间到啦! --下班都是他们的,而我,还是什么都没有. eclipse加速 去掉包含js文件的包的js验证,否则每次启动都需要进行校验(右击项目->properties) Nginx配置跨域 ...
- [网站安全] [实战分享]WEB漏洞挖掘的一些经验分享
WEB漏洞有很多种,比如SQL注入,比如XSS,比如文件包含,比如越权访问查看,比如目录遍历等等等等,漏洞带来的危害有很多,信息泄露,文件上传到GETSHELL,一直到内网渗透,这里我想分享的最主要的 ...
- SSO单点登录的发展由来以及实现原理【转】
单点登录以及权限,在很早之前都有写过,不过都比较简单,今天就具体说一下,以及下一步要做的 1.web单系统应用 早期我们开发web应用都是所有的包放在一起打成一个war包放入tomcat容器来运行的, ...
- JVM的分区+查看GC对象是否存活+3种GC算法+7种垃圾收集器+如何减少GC次数
一.JVM的分区: 1.程序计数器(私有) 程序计数器是一块较小的内存分区,你可以把它看做当前线程所执行的字节码的指示器. 在虚拟机的概念模型里,字节码解释器工作时,就是通过改变计数器的值来选择下 ...
- 大数据系列之分布式数据库HBase-0.9.8安装及增删改查实践
若查看HBase-1.2.4版本内容及demo代码详见 大数据系列之分布式数据库HBase-1.2.4+Zookeeper 安装及增删改查实践 1. 环境准备: 1.需要在Hadoop启动正常情况下安 ...
- int(long) 类型转换为char
char类型占一个字节,8位 int类型四个字节32位 (long类型的转换跟int类型相同) #include <stdio.h> ]) { buffer[] = (char)tmp; ...
- Java访问http用户验证
public class SAXParse { static final String kuser = "admin"; static final String kpass = & ...
- Myeclipse编辑jsp文件很卡是什么原因?
可能是配置问题,配置的时候不要把myeclipse连接到网络.否则每次编辑的时候要在网上查找,所以照成很卡.window->perferences->java->Installed ...
- P1084 疫情控制
Solution 二分答案, 尽量往上跳, 不能跳到根节点. 仍然能跳的拿出来.看剩下的点没有覆盖哪个? 贪心的分配一下. Code 70 #include<iostream> #incl ...