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 ...
随机推荐
- img图片居中
关键词:clear: both; display: block; margin:auto; 图片居左,居右,居中: /* Alignment */ .alignleft { display ...
- HNOI2019退役祭
对你没看错,是退役祭. Day -2 春游.话说为什么又是植物园? Day -1 白天上文化课,晚上给机房其它童鞋出题. Day 0 给他们考试,然后颓3Dmaze,毕竟没网 Day 1 车上复习了下 ...
- 图片轮播器——jquery插件
下载:http://files.cnblogs.com/files/wordblog/jiaoben828.rar
- okhttp3使用详解
http://blog.csdn.net/itachi85/article/details/51190687
- XGBoost与LightGBM对比分析(转)
尊重原创 来源: https://blog.csdn.net/a790209714/article/details/78086867 XGBoost的四大改进: ①改进残差函数 不用Gini作为残 ...
- myeclipse/eclipse安装反编译插件jadclipse
jad是一个使用比较广泛的Java反编译软件,jadClipse是jad在eclipse下的插件,下面像大家介绍下如何将jadclipse加入到myeclipse/eclipse中. 文件下载 (1) ...
- /etc/issue 与 /etc/issue.net 文件,telnet登陆前的显示
在使用文本设备(关于文本设备的例子,见下面的说明)登录Linux系统之前,系统会显示一条被称作“issue”的消息: 若是通过本地文本设备(如本地终端,本地虚拟控制台等)登录,则该信息存放与/etc/ ...
- POJ 3279 Fliptile(DFS+反转)
题目链接:http://poj.org/problem?id=3279 题目大意:有一个n*m的格子,每个格子都有黑白两面(0表示白色,1表示黑色).我们需要把所有的格子都反转成黑色,每反转一个格子, ...
- ajax刷新输出实时数据
setInterval('shuaxin()',3000); function shuaxin(){ $.ajax({//股票 url:"http://apimarkets.wallstre ...
- Hadoop案例(九)流量汇总案例
流量汇总程序案例 1.自定义输出 统计手机号耗费的总上行流量.下行流量.总流量(序列化) 1)需求: 统计每一个手机号耗费的总上行流量.下行流量.总流量 2)数据准备 phone_date.txt - ...