BZOJ3626: [LNOI2014]LCA(树链剖分+线段树)
Description
给出一个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的最近公共祖先的深度之和)
Input
第一行2个整数n q。
接下来n-1行,分别表示点1到点n-1的父节点编号。
接下来q行,每行3个整数l r z。
Output
输出q行,每行表示一个询问的答案。每个答案对201314取模输出
Sample Input
0
0
1
1
1 4 3
1 4 2
Sample Output
5
解题思路:
蒟蒻QAQ的我一开始以为是树上莫队。
还好吧,这题其实是将Deep重新理解了一下,就是从根到这个点的距离。
我们发现可以在树链上(到1)加一,最后查询到根的权值和。
发现具有区间可减性。
线段树+树剖搞定。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lll spc<<1
#define rrr spc<<1|1
typedef long long lnt;
const lnt mod=;
using std::sort;
struct trnt{
lnt lzt;
lnt val;
}tr[];
struct pnt{
int hd;
int fa;
int tp;
int dp;
int no;
int wgt;
int ind;
int mxs;
}p[];
struct ent{
int twd;
int lst;
}e[];
int ans[];
struct data{
int no;
bool lft;
int rgt;
int z;
}dt[];
int cnt;
int dfn;
int n,q;
bool cmp(data x,data y)
{
return x.rgt<y.rgt;
}
void ade(int f,int t)
{
cnt++;
e[cnt].twd=t;
e[cnt].lst=p[f].hd;
p[f].hd=cnt;
return ;
}
void add(int l,int r,int spc,lnt x)
{
if(!spc)
return ;
tr[spc].lzt=(tr[spc].lzt+x)%mod;
tr[spc].val=(tr[spc].val+(((lnt)(r-l+))*x)%mod)%mod;
return ;
}
void pushdown(int spc,int l,int r)
{
if(tr[spc].lzt)
{
int mid=(l+r)>>;
add(l,mid,lll,tr[spc].lzt);
add(mid+,r,rrr,tr[spc].lzt);
tr[spc].lzt=;
}
return ;
}
void pushup(int spc)
{
tr[spc].val=(tr[lll].val+tr[rrr].val)%mod;
}
void update(int l,int r,int ll,int rr,int spc,lnt v)
{
if(ll>r||l>rr)
return ;
if(ll<=l&&r<=rr)
{
add(l,r,spc,v);
return ;
}
pushdown(spc,l,r);
int mid=(l+r)>>;
update(l,mid,ll,rr,lll,v);
update(mid+,r,ll,rr,rrr,v);
pushup(spc);
return ;
}
lnt query(int l,int r,int ll,int rr,int spc)
{
if(ll>r||l>rr)
return 0ll;
if(ll<=l&&r<=rr)
return tr[spc].val;
int mid=(l+r)>>;
pushdown(spc,l,r);
return (query(l,mid,ll,rr,lll)+query(mid+,r,ll,rr,rrr))%mod;
}
void Basic_dfs(int x,int f)
{
p[x].fa=f;
p[x].dp=p[f].dp+;
p[x].wgt=;
int maxs=-;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==f)
continue;
Basic_dfs(to,x);
p[x].wgt+=p[to].wgt;
if(p[to].wgt>maxs)
{
maxs=p[to].wgt;
p[x].mxs=to;
}
}
}
void Build_dfs(int x,int top)
{
if(!x)
return ;
p[x].ind=++dfn;
p[x].tp=top;
Build_dfs(p[x].mxs,top);
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].ind)
continue;
Build_dfs(to,to);
}
return ;
}
void Insert(int x)
{
while(p[x].tp!=)
{
update(,n,p[p[x].tp].ind,p[x].ind,,);
x=p[p[x].tp].fa;
}
update(,n,,p[x].ind,,);
return ;
}
lnt Val(int x)
{
lnt ansl=;
while(p[x].tp!=)
{
ansl+=query(,n,p[p[x].tp].ind,p[x].ind,);
ansl%=mod;
x=p[p[x].tp].fa;
}
ansl+=query(,n,,p[x].ind,);
ansl%=mod;
return ansl;
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=;i<=n;i++)
{
int a;
scanf("%d",&a);
a++;
ade(a,i);
ade(i,a);
}
cnt=;
for(int i=;i<=q;i++)
{
int tmp;
cnt++;
dt[cnt].no=i;
dt[cnt].lft=true;
scanf("%d",&dt[cnt].rgt);
cnt++;
dt[cnt].no=i;
dt[cnt].lft=false;
scanf("%d",&dt[cnt].rgt);
dt[cnt].rgt++;
scanf("%d",&tmp);
tmp++;
dt[cnt].z=dt[cnt-].z=tmp;
}
sort(dt+,dt+cnt+,cmp);
Basic_dfs(,);
Build_dfs(,);
int plc=;
for(int i=;i<=cnt;i++)
{
while(plc<=dt[i].rgt)
{
Insert(plc);
plc++;
}
int x=dt[i].no;
int pl=dt[i].z;
lnt tmp=Val(pl);
if(dt[i].lft)
tmp=-tmp;
ans[x]=(ans[x]+tmp)%mod;
}
for(int i=;i<=q;i++)
printf("%lld\n",(ans[i]%mod+mod)%mod);
return ;
}
BZOJ3626: [LNOI2014]LCA(树链剖分+线段树)的更多相关文章
- 【bzoj3626】[LNOI2014]LCA 树链剖分+线段树
题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...
- 【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 ...
- BZOJ3862Little Devil I——树链剖分+线段树
题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...
- BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树
题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...
- BZOJ2819Nim——树链剖分+线段树+Nim游戏
题目描述 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略 ...
- POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )
POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
- [HDU3710] Battle Over Cities [树链剖分+线段树+并查集+kruskal+思维]
题面 一句话题意: 给定一张 N 个点, M 条边的无向连通图, 每条边上有边权 w . 求删去任意一个点后的最小生成树的边权之和. 思路 首先肯定要$kruskal$一下 考虑$MST$里面去掉一个 ...
随机推荐
- 7-07. PAT排名汇总(25) (结构体 ZJU_PAT)
题目链接:http://www.patest.cn/contests/ds/7-07 编程能力測试(Programming Ability Test,简称PAT)是浙江大学计算机科学与技术学院主办的专 ...
- spring IOC --- 控制反转(依赖注入)----简单的实例
IoC(Inversion of Control)控制反转,对象创建责任的反转,在spring中BeanFacotory是IoC容器的核心接口,负责实例化,定位,配置应用程序中的对象及建立这些对象间的 ...
- OpenJDK源码研究笔记(十二):JDBC中的元数据,数据库元数据(DatabaseMetaData),参数元数据(ParameterMetaData),结果集元数据(ResultSetMetaDa
元数据最本质.最抽象的定义为:data about data (关于数据的数据).它是一种广泛存在的现象,在许多领域有其具体的定义和应用. JDBC中的元数据,有数据库元数据(DatabaseMeta ...
- cogs 1500. 误差曲线
1500. 误差曲线 ★★ 输入文件:errorcurves.in 输出文件:errorcurves.out 评测插件时间限制:1 s 内存限制:256 MB [题目描述] Josep ...
- jQuery源码05 (3653 , 3797) queue() : 队列方法 : 执行顺序的管理
//对外接口 jQuery.extend({ queue: function( elem, type, data ) {//入队.元素.队列名字.存进去的函数 //jQuery.queue( this ...
- modSecurity规则学习(三)——SecRule
通用格式 SecRule VARIABLES OPERATOR [TRANSFORMATION_FUNCTIONS, ACTIONS] 阶段phase (1)request headers (2) ...
- c++中重载、重写、覆盖的区别
Overload(重载):在C++程序中,可以将语义.功能相似的几个函数用同一个名字表示,但参数或返回值不同(包括类型.顺序不同),即函数重载.(1)相同的范围(在同一个类中):(2)函数名字相同:( ...
- es6 -- Iterator 和 for...of 循环
1:Iterator(遍历器)的概念 JavaScript 原有的表示“集合”的数据结构,主要是数组(Array)和对象(Object),ES6 又添加了Map和Set.这样就有了四种数据集合,用户还 ...
- vue -- 动态加载组件 (tap 栏效果)
在 vue 中,实现 Tab 切换主要有三种方式:使用动态组件,使用 vue-router 路由,使用第三方插件. 因为这次完成的功能只是简单切换组件,再则觉得使用路由切换需要改变地址略微麻烦,所以使 ...
- Fragment-传递参数
在关Fragment间参数的传递,有两种情况: 第一种情况:同一个container中不同fragment间的参数传递.这种情况一般发生在fragment跳转时,上一个Fragment将参数传递给下一 ...