引用题解:

http://blog.csdn.net/popoqqq/article/details/38823457

题目大意:

给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。
有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)]。
(即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)

这题看见了直接卡壳。。。然后看了题解才搞懂要怎么写。。。

直接复制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),均可以完成任务。至此,题目已经被我们完美解决。

写的很详细,我就不累述了

同样是14年的省选,同样是树链剖分,为啥辽宁省的就如此牛B,吉林省的就是水题。。。差距好大0.0

取模的话数字不是很大 可以开long long 最后取一下模就好了 中途不要取模 弄成负的WA了我一下午0.0 又一下午0.0 又一下午0.0 啊啊啊啊啊啊啊啊啊

——PoPoQQQ

#include<cstdio>
#include<algorithm>
using namespace std;
#define N 50001
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
struct ASK{int p,z,id;}Q[N<<1];
int n,m;
bool operator < (const ASK &a,const ASK &b){return a.p<b.p;}
int sumv[N<<2],delta[N<<2];
void pushdown(int rt,int sz)
{
if(delta[rt])
{
sumv[rt<<1]+=(sz-(sz>>1))*delta[rt];
sumv[rt<<1|1]+=(sz>>1)*delta[rt];
delta[rt<<1]+=delta[rt];
delta[rt<<1|1]+=delta[rt];
delta[rt]=0;
}
}
void update(int ql,int qr,int rt,int l,int r)
{
if(ql<=l&&r<=qr)
{
sumv[rt]+=(r-l+1);
++delta[rt];
return;
}
pushdown(rt,r-l+1);
int m=(l+r>>1);
if(ql<=m) update(ql,qr,lson);
if(m<qr) update(ql,qr,rson);
sumv[rt]=sumv[rt<<1]+sumv[rt<<1|1];
}
int query(int ql,int qr,int rt,int l,int r)
{
if(ql<=l&&r<=qr) return sumv[rt];
pushdown(rt,r-l+1);
int m=(l+r>>1),res=0;
if(ql<=m) res+=query(ql,qr,lson);
if(m<qr) res+=query(ql,qr,rson);
return res;
}
int v[N],en,first[N],next[N];
void AddEdge(int U,int V)
{
v[++en]=V;
next[en]=first[U];
first[U]=en;
}
int top[N],tot,Num[N],fa[N],siz[N],son[N];
void dfs(int U)
{
siz[U]=1;
for(int i=first[U];i;i=next[i])
{
dfs(v[i]);
siz[U]+=siz[v[i]];
if(siz[v[i]]>siz[son[U]])
son[U]=v[i];
}
}
void df2(int U)
{
Num[U]=++tot;
if(son[U])
{
top[son[U]]=top[U];
df2(son[U]);
}
for(int i=first[U];i;i=next[i])
if(v[i]!=son[U])
{
top[v[i]]=v[i];
df2(v[i]);
}
}
void Update(int U)
{
while(top[U]!=1)
{
update(Num[top[U]],Num[U],1,1,n);
U=fa[top[U]];
}
update(1,Num[U],1,1,n);
}
int Query(int U)
{
int res=0;
while(top[U]!=1)
{
res+=query(Num[top[U]],Num[U],1,1,n);
U=fa[top[U]];
}
return res+query(1,Num[U],1,1,n);
}
int pre[N],ans[N];
int main()
{
int x;
scanf("%d%d",&n,&m);
for(int i=2;i<=n;++i)
{
scanf("%d",&x);
AddEdge(x+1,i);
fa[i]=x+1;
}
top[1]=1;
dfs(1);
df2(1);
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&Q[(i<<1)-1].p,&Q[i<<1].p,&Q[(i<<1)-1].z);
++Q[(i<<1)-1].z;
++Q[i<<1].p;
Q[(i<<1)-1].id=(i<<1)-1;
Q[i<<1].z=Q[(i<<1)-1].z;
Q[i<<1].id=(i<<1);
}
sort(Q+1,Q+(m<<1|1));
for(int i=1;i<=(m<<1);++i)
{
for(int j=Q[i-1].p+1;j<=Q[i].p;++j)
Update(j);
if(!(Q[i].id&1)) ans[Q[i].id>>1]=Query(Q[i].z)-pre[Q[i].id>>1];
else pre[(Q[i].id+1)>>1]=Query(Q[i].z);
}
for(int i=1;i<=m;++i)
printf("%d\n",ans[i]%201314);
return 0;

【树链剖分】【线段树】bzoj3626 [LNOI2014]LCA的更多相关文章

  1. 【树链剖分 差分】bzoj3626: [LNOI2014]LCA

    把LCA深度转化的那一步还是挺妙的.之后就是差分加大力数据结构了. Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep ...

  2. 【bzoj3626】[LNOI2014]LCA 树链剖分+线段树

    题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...

  3. 【BZOJ-2325】道馆之战 树链剖分 + 线段树

    2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 1153  Solved: 421[Submit][Statu ...

  4. 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 ...

  5. bzoj2243[SDOI2011]染色 树链剖分+线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9012  Solved: 3375[Submit][Status ...

  6. BZOJ3862Little Devil I——树链剖分+线段树

    题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...

  7. BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树

    题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...

  8. BZOJ2819Nim——树链剖分+线段树+Nim游戏

    题目描述 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略 ...

  9. POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )

    POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...

  10. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

随机推荐

  1. linux 条件判断式

    1.利用if ...then if [ 判断条件 ];then 指令 fi 实例一 Y/N: #!/bin/bash #Program: # This program shows "Hell ...

  2. javaScript获取文档中所有元素节点的个数

    HTML+JS 代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...

  3. charles 踩坑记录

    charles破解教程:http://www.jianshu.com/p/12e75eb8f53d 1.需注意软件和破解脚本的版本是否正确(例如3.x.x版本的破解脚本不能用于4.x.x版本的char ...

  4. commons

    <!-- https://mvnrepository.com/artifact/commons-lang/commons-lang --> <dependency> <g ...

  5. 【Atcoder】ARC 080 F - Prime Flip

    [算法]数论,二分图最大匹配 [题意]有无限张牌,给定n张面朝上的牌的坐标(N<=100),其它牌面朝下,每次操作可以选定一个>=3的素数p,并翻转连续p张牌,求最少操作次数使所有牌向下. ...

  6. 【洛谷 P1896】[SCOI2005]互不侵犯(状压dp)

    题目链接 题意:在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 这是道状压\(DP\)好题啊.. ...

  7. mongoDB的简单使用

    1.客户端连接: ./mongo 2.数据库 一个mongodb中可以建立多个数据库. MongoDB的默认数据库为"db",该数据库存储在data目录中. MongoDB的单个实 ...

  8. Hadoop安装过程

    1.安装JDK apt-get install openjdk-7-jdk 2.配置环境变量 vim /etc/profile 编辑: export JAVA_HOME=/usr/lib/jvm/ja ...

  9. HDU2444(判断是否为二分图,求最大匹配)

    The Accomodation of Students Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ( ...

  10. linux sun/awt/X11GraphicsEnvironment 找不到错误

    转载自:http://blog.csdn.net/bolg_hero/article/details/46594915 在Linux下,我们在用Java的图片包来处理图片时,经常遇到java.lang ...